Merge "[flexiglass] Update NSSL clipping based on Composable placeholder" into main
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index c49c197..12f1b30 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -27,11 +27,13 @@
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.layout.LayoutCoordinates
 import androidx.compose.ui.layout.boundsInWindow
 import androidx.compose.ui.layout.onPlaced
@@ -89,13 +91,18 @@
     isScrimVisible: Boolean,
     modifier: Modifier = Modifier,
 ) {
+    val cornerRadius by viewModel.cornerRadiusDp.collectAsState()
+
     Box(modifier = modifier) {
         if (isScrimVisible) {
             Box(
                 modifier =
                     Modifier.element(Notifications.Elements.NotificationScrim)
                         .fillMaxSize()
-                        .clip(RoundedCornerShape(32.dp))
+                        .graphicsLayer {
+                            shape = RoundedCornerShape(cornerRadius.dp)
+                            clip = true
+                        }
                         .background(MaterialTheme.colorScheme.surface)
             )
         }
@@ -167,7 +174,9 @@
                     }
                     val boundsInWindow = coordinates.boundsInWindow()
                     viewModel.onBoundsChanged(
+                        left = boundsInWindow.left,
                         top = boundsInWindow.top,
+                        right = boundsInWindow.right,
                         bottom = boundsInWindow.bottom,
                     )
                 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
index 28f3e93..4cdb08a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
@@ -67,9 +67,24 @@
             val bounds by collectLastValue(appearanceViewModel.stackBounds)
 
             val top = 200f
+            val left = 0f
             val bottom = 550f
-            placeholderViewModel.onBoundsChanged(top, bottom)
-            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom))
+            val right = 100f
+            placeholderViewModel.onBoundsChanged(
+                left = left,
+                top = top,
+                right = right,
+                bottom = bottom
+            )
+            assertThat(bounds)
+                .isEqualTo(
+                    NotificationContainerBounds(
+                        left = left,
+                        top = top,
+                        right = right,
+                        bottom = bottom
+                    )
+                )
         }
 
     @Test
diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
index fdd98bec..3063ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
@@ -18,8 +18,12 @@
 
 /** Models the bounds of the notification container. */
 data class NotificationContainerBounds(
+    /** The position of the left of the container in its window coordinate system, in pixels. */
+    val left: Float = 0f,
     /** The position of the top of the container in its window coordinate system, in pixels. */
     val top: Float = 0f,
+    /** The position of the right of the container in its window coordinate system, in pixels. */
+    val right: Float = 0f,
     /** The position of the bottom of the container in its window coordinate system, in pixels. */
     val bottom: Float = 0f,
     /** Whether any modifications to top/bottom should be smoothly animated. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
index a25471c..e88a975 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
@@ -85,9 +85,9 @@
             )
         if (sceneContainerFlags.flexiNotifsEnabled()) {
             NotificationStackAppearanceViewBinder.bind(
+                context,
                 sharedNotificationContainer,
                 notificationStackAppearanceViewModel,
-                sceneContainerFlags,
                 ambientState,
                 controller,
             )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 4588e02..d9697db 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -229,7 +229,9 @@
             .distinctUntilChanged()
 
     fun onNotificationContainerBoundsChanged(top: Float, bottom: Float) {
-        keyguardInteractor.setNotificationContainerBounds(NotificationContainerBounds(top, bottom))
+        keyguardInteractor.setNotificationContainerBounds(
+            NotificationContainerBounds(top = top, bottom = bottom)
+        )
     }
 
     /** Is there an expanded pulse, are we animating in response? */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
index abf09ae..e78a694 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
@@ -26,5 +26,8 @@
 @SysUISingleton
 class NotificationStackAppearanceRepository @Inject constructor() {
     /** The bounds of the notification stack in the current scene. */
-    val stackBounds = MutableStateFlow(NotificationContainerBounds(0f, 0f))
+    val stackBounds = MutableStateFlow(NotificationContainerBounds())
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp = MutableStateFlow(32f)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index 32e4e89..61a4dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -39,4 +39,7 @@
         check(bounds.top <= bounds.bottom) { "Invalid bounds: $bounds" }
         repository.stackBounds.value = bounds
     }
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = repository.cornerRadiusDp.asStateFlow()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
index fa7a8fd..a9b542d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
@@ -16,14 +16,16 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewbinder
 
+import android.content.Context
+import android.util.TypedValue
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.statusbar.notification.stack.AmbientState
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
+import kotlin.math.roundToInt
 import kotlinx.coroutines.launch
 
 /** Binds the shared notification container to its view-model. */
@@ -31,9 +33,9 @@
 
     @JvmStatic
     fun bind(
+        context: Context,
         view: SharedNotificationContainer,
         viewModel: NotificationStackAppearanceViewModel,
-        sceneContainerFlags: SceneContainerFlags,
         ambientState: AmbientState,
         controller: NotificationStackScrollLayoutController,
     ) {
@@ -45,6 +47,14 @@
                             bounds.top,
                             controller.isAddOrRemoveAnimationPending
                         )
+                        controller.setRoundedClippingBounds(
+                            it.left,
+                            it.top,
+                            it.right,
+                            it.bottom,
+                            viewModel.cornerRadiusDp.value.dpToPx(context),
+                            viewModel.cornerRadiusDp.value.dpToPx(context),
+                        )
                     }
                 }
                 launch {
@@ -56,4 +66,13 @@
             }
         }
     }
+
+    private fun Float.dpToPx(context: Context): Int {
+        return TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP,
+                this,
+                context.resources.displayMetrics
+            )
+            .roundToInt()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
index f4c0e92..834d3ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 
 /** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
 @SysUISingleton
@@ -37,4 +38,7 @@
 
     /** The bounds of the notification stack in the current scene. */
     val stackBounds: Flow<NotificationContainerBounds> = stackAppearanceInteractor.stackBounds
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = stackAppearanceInteractor.cornerRadiusDp
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
index c6fd98e..9f22118 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled
 import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
 
 /**
  * ViewModel used by the Notification placeholders inside the scene container to update the
@@ -55,9 +56,14 @@
      *   pixels.
      */
     fun onBoundsChanged(
+        left: Float,
         top: Float,
+        right: Float,
         bottom: Float,
     ) {
-        interactor.setStackBounds(NotificationContainerBounds(top, bottom))
+        interactor.setStackBounds(NotificationContainerBounds(left, top, right, bottom))
     }
+
+    /** The corner radius of the placeholder, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = interactor.cornerRadiusDp
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 5b854e6..ffbc6ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -178,7 +178,7 @@
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = NotificationContainerBounds(0f, 0f),
+                initialValue = NotificationContainerBounds(),
             )
 
     val alpha: Flow<Float> =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 85b9392..f0205b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -413,7 +413,7 @@
             val top = 123f
             val bottom = 456f
             keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom)
-            assertThat(bounds).isEqualTo(NotificationContainerBounds(top, bottom))
+            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom))
         }
 
     @Test