diff options
author | 2025-03-21 12:31:02 -0700 | |
---|---|---|
committer | 2025-03-21 12:31:02 -0700 | |
commit | 30917f7b684f67aa72cc9c43c676a0b2ac624625 (patch) | |
tree | 7d78d622c0844bd0fd8c82b3b8829d3b07d4e98b | |
parent | 8c2618bd8d5f1b2ad6ed4979ac3ae04c559a7cd9 (diff) | |
parent | 436a937d3efffd7c3237a6b745144b2fc424370f (diff) |
Merge changes Ib1a98438,I3d09709a into main
* changes:
[Flexiglass] Wire in CUJ_NOTIFICATION_SHADE_SCROLL_FLING
[Flexiglass] Remove Modifier.stackVerticalOverscroll
7 files changed, 220 insertions, 164 deletions
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt index cb713ece12a5..5ed72c7d94a2 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt @@ -55,7 +55,12 @@ open class BaseContentOverscrollEffect( get() = animatable.value override val isInProgress: Boolean - get() = overscrollDistance != 0f + /** + * We need both checks, because [overscrollDistance] can be + * - zero while it is already being animated, if the animation starts from 0 + * - greater than zero without an animation, if the content is still being dragged + */ + get() = overscrollDistance != 0f || animatable.isRunning override fun applyToScroll( delta: Offset, diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt index e7c47fb56130..8a1fa3724d15 100644 --- a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt +++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt @@ -16,12 +16,17 @@ package com.android.compose.gesture.effect +import androidx.compose.foundation.OverscrollEffect import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.ScrollableState import androidx.compose.foundation.gestures.rememberScrollableState import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.overscroll +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.platform.LocalDensity @@ -32,11 +37,14 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.swipeWithVelocity import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import kotlin.properties.Delegates +import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -47,7 +55,13 @@ class OffsetOverscrollEffectTest { private val BOX_TAG = "box" - private data class LayoutInfo(val layoutSize: Dp, val touchSlop: Float, val density: Density) { + private data class LayoutInfo( + val layoutSize: Dp, + val touchSlop: Float, + val density: Density, + val scrollableState: ScrollableState, + val overscrollEffect: OverscrollEffect, + ) { fun expectedOffset(currentOffset: Dp): Dp { return with(density) { OffsetOverscrollEffect.computeOffset(this, currentOffset.toPx()).toDp() @@ -55,22 +69,29 @@ class OffsetOverscrollEffectTest { } } - private fun setupOverscrollableBox(scrollableOrientation: Orientation): LayoutInfo { + private fun setupOverscrollableBox( + scrollableOrientation: Orientation, + canScroll: () -> Boolean, + ): LayoutInfo { val layoutSize: Dp = 200.dp var touchSlop: Float by Delegates.notNull() // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is // detected as a drag event. lateinit var density: Density + lateinit var scrollableState: ScrollableState + lateinit var overscrollEffect: OverscrollEffect + rule.setContent { density = LocalDensity.current touchSlop = LocalViewConfiguration.current.touchSlop - val overscrollEffect = rememberOffsetOverscrollEffect() + scrollableState = rememberScrollableState { if (canScroll()) it else 0f } + overscrollEffect = rememberOffsetOverscrollEffect() Box( Modifier.overscroll(overscrollEffect) // A scrollable that does not consume the scroll gesture. .scrollable( - state = rememberScrollableState { 0f }, + state = scrollableState, orientation = scrollableOrientation, overscrollEffect = overscrollEffect, ) @@ -78,12 +99,16 @@ class OffsetOverscrollEffectTest { .testTag(BOX_TAG) ) } - return LayoutInfo(layoutSize, touchSlop, density) + return LayoutInfo(layoutSize, touchSlop, density, scrollableState, overscrollEffect) } @Test fun applyVerticalOffset_duringVerticalOverscroll() { - val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical) + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { false }, + ) rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp) @@ -99,7 +124,11 @@ class OffsetOverscrollEffectTest { @Test fun applyNoOffset_duringHorizontalOverscroll() { - val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical) + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { false }, + ) rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp) @@ -113,7 +142,11 @@ class OffsetOverscrollEffectTest { @Test fun backToZero_afterOverscroll() { - val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical) + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { false }, + ) rule.onRoot().performTouchInput { down(center) @@ -131,7 +164,11 @@ class OffsetOverscrollEffectTest { @Test fun offsetOverscroll_followTheTouchPointer() { - val info = setupOverscrollableBox(scrollableOrientation = Orientation.Vertical) + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { false }, + ) // First gesture, drag down. rule.onRoot().performTouchInput { @@ -165,4 +202,130 @@ class OffsetOverscrollEffectTest { .onNodeWithTag(BOX_TAG) .assertTopPositionInRootIsEqualTo(info.expectedOffset(-info.layoutSize)) } + + @Test + fun isScrollInProgress_overscroll() = runTest { + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { false }, + ) + + // Start a swipe gesture, and swipe down to start an overscroll. + rule.onRoot().performTouchInput { + down(center) + moveBy(Offset(0f, info.touchSlop + info.layoutSize.toPx() / 2)) + } + + assertThat(info.scrollableState.isScrollInProgress).isTrue() + assertThat(info.overscrollEffect.isInProgress).isTrue() + + // Finish the swipe gesture. + rule.onRoot().performTouchInput { up() } + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isTrue() + + // Wait until the overscroll returns to idle. + rule.awaitIdle() + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isFalse() + } + + @Test + fun isScrollInProgress_scroll() = runTest { + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { true }, + ) + + rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp) + + // Start a swipe gesture, and swipe down to scroll. + rule.onRoot().performTouchInput { + down(center) + moveBy(Offset(0f, info.touchSlop + info.layoutSize.toPx() / 2)) + } + + assertThat(info.scrollableState.isScrollInProgress).isTrue() + assertThat(info.overscrollEffect.isInProgress).isFalse() + + // Finish the swipe gesture. + rule.onRoot().performTouchInput { up() } + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isTrue() + + // Wait until the overscroll returns to idle. + rule.awaitIdle() + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isFalse() + } + + @Test + fun isScrollInProgress_flingToScroll() = runTest { + val info = + setupOverscrollableBox( + scrollableOrientation = Orientation.Vertical, + canScroll = { true }, + ) + + rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp) + + // Swipe down and leave some velocity to start a fling. + rule.onRoot().performTouchInput { + swipeWithVelocity( + Offset.Zero, + Offset(0f, info.touchSlop + info.layoutSize.toPx() / 2), + endVelocity = 100f, + ) + } + + assertThat(info.scrollableState.isScrollInProgress).isTrue() + assertThat(info.overscrollEffect.isInProgress).isFalse() + + // Wait until the fling is finished. + rule.awaitIdle() + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isFalse() + } + + @Test + fun isScrollInProgress_flingToOverscroll() = runTest { + // Start with a scrollable state. + var canScroll by mutableStateOf(true) + val info = + setupOverscrollableBox(scrollableOrientation = Orientation.Vertical) { canScroll } + + rule.onNodeWithTag(BOX_TAG).assertTopPositionInRootIsEqualTo(0.dp) + + // Swipe down and leave some velocity to start a fling. + rule.onRoot().performTouchInput { + swipeWithVelocity( + Offset.Zero, + Offset(0f, info.touchSlop + info.layoutSize.toPx() / 2), + endVelocity = 100f, + ) + } + + assertThat(info.scrollableState.isScrollInProgress).isTrue() + assertThat(info.overscrollEffect.isInProgress).isFalse() + + // The fling reaches the end of the scrollable region, and an overscroll starts. + canScroll = false + rule.mainClock.advanceTimeUntil { !info.scrollableState.isScrollInProgress } + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isTrue() + + // Wait until the overscroll returns to idle. + rule.awaitIdle() + + assertThat(info.scrollableState.isScrollInProgress).isFalse() + assertThat(info.overscrollEffect.isInProgress).isFalse() + } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt deleted file mode 100644 index e1ee59ba0626..000000000000 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.notifications.ui.composable - -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.tween -import androidx.compose.foundation.gestures.FlingBehavior -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.ScrollableDefaults -import androidx.compose.foundation.layout.offset -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.NestedScrollConnection -import androidx.compose.ui.input.nestedscroll.NestedScrollSource -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.Velocity -import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastCoerceAtLeast -import com.android.compose.nestedscroll.OnStopScope -import com.android.compose.nestedscroll.PriorityNestedScrollConnection -import com.android.compose.nestedscroll.ScrollController -import kotlin.math.max -import kotlin.math.roundToInt -import kotlin.math.tanh -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch - -@Composable -fun Modifier.stackVerticalOverscroll( - coroutineScope: CoroutineScope, - canScrollForward: () -> Boolean, -): Modifier { - val screenHeight = - with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() } - val overscrollOffset = remember { Animatable(0f) } - val flingBehavior = ScrollableDefaults.flingBehavior() - val stackNestedScrollConnection = - remember(flingBehavior) { - NotificationStackNestedScrollConnection( - stackOffset = { overscrollOffset.value }, - canScrollForward = canScrollForward, - onScroll = { offsetAvailable -> - coroutineScope.launch { - val maxProgress = screenHeight * 0.2f - val tilt = 3f - var offset = - overscrollOffset.value + - maxProgress * tanh(x = offsetAvailable / (maxProgress * tilt)) - offset = max(offset, -1f * maxProgress) - overscrollOffset.snapTo(offset) - } - }, - onStop = { velocityAvailable -> - coroutineScope.launch { - overscrollOffset.animateTo( - targetValue = 0f, - initialVelocity = velocityAvailable, - animationSpec = tween(), - ) - } - }, - flingBehavior = flingBehavior, - ) - } - - return this.then( - Modifier.nestedScroll( - remember { - object : NestedScrollConnection { - override suspend fun onPostFling( - consumed: Velocity, - available: Velocity, - ): Velocity { - return if (available.y < 0f && !canScrollForward()) { - overscrollOffset.animateTo( - targetValue = 0f, - initialVelocity = available.y, - animationSpec = tween(), - ) - available - } else { - Velocity.Zero - } - } - } - } - ) - .nestedScroll(stackNestedScrollConnection) - .offset { IntOffset(x = 0, y = overscrollOffset.value.roundToInt()) } - ) -} - -fun NotificationStackNestedScrollConnection( - stackOffset: () -> Float, - canScrollForward: () -> Boolean, - onStart: (Float) -> Unit = {}, - onScroll: (Float) -> Unit, - onStop: (Float) -> Unit = {}, - flingBehavior: FlingBehavior, -): PriorityNestedScrollConnection { - return PriorityNestedScrollConnection( - orientation = Orientation.Vertical, - canStartPreScroll = { _, _, _ -> false }, - canStartPostScroll = { offsetAvailable, offsetBeforeStart, _ -> - offsetAvailable < 0f && offsetBeforeStart < 0f && !canScrollForward() - }, - onStart = { firstScroll -> - onStart(firstScroll) - object : ScrollController { - override fun onScroll(deltaScroll: Float, source: NestedScrollSource): Float { - val minOffset = 0f - val consumed = deltaScroll.fastCoerceAtLeast(minOffset - stackOffset()) - if (consumed != 0f) { - onScroll(consumed) - } - return consumed - } - - override suspend fun OnStopScope.onStop(initialVelocity: Float): Float { - val consumedByScroll = flingToScroll(initialVelocity, flingBehavior) - onStop(initialVelocity - consumedByScroll) - return initialVelocity - } - - override fun onCancel() { - onStop(0f) - } - - override fun canStopOnPreFling() = false - } - }, - ) -} 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 79b346439d5d..2f9cfb6aa211 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 @@ -78,6 +78,7 @@ import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset @@ -92,7 +93,11 @@ import com.android.compose.animation.scene.LowestZIndexContentPicker import com.android.compose.animation.scene.SceneTransitionLayoutState import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.gesture.NestedScrollableBound +import com.android.compose.gesture.effect.OffsetOverscrollEffect +import com.android.compose.gesture.effect.rememberOffsetOverscrollEffect import com.android.compose.modifiers.thenIf +import com.android.internal.jank.InteractionJankMonitor +import com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession @@ -288,17 +293,19 @@ fun ContentScope.NotificationScrollingStack( shadeSession: SaveableSession, stackScrollView: NotificationScrollView, viewModel: NotificationsPlaceholderViewModel, + jankMonitor: InteractionJankMonitor, maxScrimTop: () -> Float, shouldPunchHoleBehindScrim: Boolean, stackTopPadding: Dp, stackBottomPadding: Dp, + modifier: Modifier = Modifier, shouldFillMaxSize: Boolean = true, shouldIncludeHeadsUpSpace: Boolean = true, shouldShowScrim: Boolean = true, supportNestedScrolling: Boolean, onEmptySpaceClick: (() -> Unit)? = null, - modifier: Modifier = Modifier, ) { + val composeViewRoot = LocalView.current val coroutineScope = shadeSession.sessionCoroutineScope() val density = LocalDensity.current val screenCornerRadius = LocalScreenCornerRadius.current @@ -477,6 +484,21 @@ fun ContentScope.NotificationScrollingStack( ) } + val overScrollEffect: OffsetOverscrollEffect = rememberOffsetOverscrollEffect() + // whether the stack is moving due to a swipe or fling + val isScrollInProgress = + scrollState.isScrollInProgress || overScrollEffect.isInProgress || scrimOffset.isRunning + + LaunchedEffect(isScrollInProgress) { + if (isScrollInProgress) { + jankMonitor.begin(composeViewRoot, CUJ_NOTIFICATION_SHADE_SCROLL_FLING) + debugLog(viewModel) { "STACK scroll begins" } + } else { + debugLog(viewModel) { "STACK scroll ends" } + jankMonitor.end(CUJ_NOTIFICATION_SHADE_SCROLL_FLING) + } + } + Box( modifier = modifier @@ -577,8 +599,7 @@ fun ContentScope.NotificationScrollingStack( .thenIf(supportNestedScrolling) { Modifier.nestedScroll(scrimNestedScrollConnection) } - .stackVerticalOverscroll(coroutineScope) { scrollState.canScrollForward } - .verticalScroll(scrollState) + .verticalScroll(scrollState, overscrollEffect = overScrollEffect) .padding(top = stackTopPadding, bottom = stackBottomPadding) .fillMaxWidth() .onGloballyPositioned { coordinates -> diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt index 37ce358a2a98..6d37e0affd6a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt @@ -29,6 +29,7 @@ import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult +import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn import com.android.systemui.keyguard.ui.composable.section.DefaultClockSection @@ -69,6 +70,7 @@ constructor( private val keyguardClockViewModel: KeyguardClockViewModel, private val mediaCarouselController: MediaCarouselController, @Named(QUICK_QS_PANEL) private val mediaHost: Lazy<MediaHost>, + private val jankMonitor: InteractionJankMonitor, ) : Overlay { override val key = Overlays.NotificationsShade @@ -146,6 +148,7 @@ constructor( shadeSession = shadeSession, stackScrollView = stackScrollView.get(), viewModel = placeholderViewModel, + jankMonitor = jankMonitor, maxScrimTop = { 0f }, shouldPunchHoleBehindScrim = false, stackTopPadding = notificationStackPadding, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 0a711487ccb1..d667f68e4fdd 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -75,6 +75,7 @@ import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.modifiers.thenIf import com.android.compose.windowsizeclass.LocalWindowSizeClass +import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout import com.android.systemui.compose.modifiers.sysuiResTag @@ -126,6 +127,7 @@ constructor( private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory, private val mediaCarouselController: MediaCarouselController, @Named(MediaModule.QS_PANEL) private val mediaHost: MediaHost, + private val jankMonitor: InteractionJankMonitor, ) : ExclusiveActivatable(), Scene { override val key = Scenes.QuickSettings @@ -165,6 +167,7 @@ constructor( mediaHost = mediaHost, modifier = modifier, shadeSession = shadeSession, + jankMonitor = jankMonitor, ) } @@ -186,6 +189,7 @@ private fun ContentScope.QuickSettingsScene( mediaHost: MediaHost, modifier: Modifier = Modifier, shadeSession: SaveableSession, + jankMonitor: InteractionJankMonitor, ) { val cutoutLocation = LocalDisplayCutout.current.location val brightnessMirrorShowing by brightnessMirrorViewModel.isShowing.collectAsStateWithLifecycle() @@ -432,6 +436,7 @@ private fun ContentScope.QuickSettingsScene( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, + jankMonitor = jankMonitor, maxScrimTop = { minNotificationStackTop.toFloat() }, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, stackTopPadding = notificationStackPadding, 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 885d34fb95c9..60e32d7ce824 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 @@ -73,6 +73,7 @@ import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.modifiers.padding import com.android.compose.modifiers.thenIf +import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout @@ -145,6 +146,7 @@ constructor( private val mediaCarouselController: MediaCarouselController, @Named(QUICK_QS_PANEL) private val qqsMediaHost: MediaHost, @Named(QS_PANEL) private val qsMediaHost: MediaHost, + private val jankMonitor: InteractionJankMonitor, ) : ExclusiveActivatable(), Scene { override val key = Scenes.Shade @@ -182,6 +184,7 @@ constructor( mediaCarouselController = mediaCarouselController, qqsMediaHost = qqsMediaHost, qsMediaHost = qsMediaHost, + jankMonitor = jankMonitor, modifier = modifier, shadeSession = shadeSession, usingCollapsedLandscapeMedia = @@ -212,6 +215,7 @@ private fun ContentScope.ShadeScene( mediaCarouselController: MediaCarouselController, qqsMediaHost: MediaHost, qsMediaHost: MediaHost, + jankMonitor: InteractionJankMonitor, modifier: Modifier = Modifier, shadeSession: SaveableSession, usingCollapsedLandscapeMedia: Boolean, @@ -229,6 +233,7 @@ private fun ContentScope.ShadeScene( modifier = modifier, shadeSession = shadeSession, usingCollapsedLandscapeMedia = usingCollapsedLandscapeMedia, + jankMonitor = jankMonitor, ) is ShadeMode.Split -> SplitShade( @@ -240,6 +245,7 @@ private fun ContentScope.ShadeScene( mediaHost = qsMediaHost, modifier = modifier, shadeSession = shadeSession, + jankMonitor = jankMonitor, ) is ShadeMode.Dual -> error("Dual shade is implemented separately as an overlay.") } @@ -253,6 +259,7 @@ private fun ContentScope.SingleShade( notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, mediaCarouselController: MediaCarouselController, mediaHost: MediaHost, + jankMonitor: InteractionJankMonitor, modifier: Modifier = Modifier, shadeSession: SaveableSession, usingCollapsedLandscapeMedia: Boolean, @@ -379,6 +386,7 @@ private fun ContentScope.SingleShade( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, + jankMonitor = jankMonitor, maxScrimTop = { maxNotifScrimTop.toFloat() }, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, stackTopPadding = notificationStackPadding, @@ -419,6 +427,7 @@ private fun ContentScope.SplitShade( mediaHost: MediaHost, modifier: Modifier = Modifier, shadeSession: SaveableSession, + jankMonitor: InteractionJankMonitor, ) { val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsStateWithLifecycle() val isQsEnabled by viewModel.isQsEnabled.collectAsStateWithLifecycle() @@ -596,6 +605,7 @@ private fun ContentScope.SplitShade( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, + jankMonitor = jankMonitor, maxScrimTop = { 0f }, stackTopPadding = notificationStackPadding, stackBottomPadding = notificationStackPadding, |