Loading core/java/com/android/internal/jank/Cuj.java +49 −1 Original line number Diff line number Diff line Loading @@ -476,8 +476,44 @@ public class Cuj { */ public static final int CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN = 144; /** * Tracks show animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI starts to show and ends when cue bar UI show * completely. */ public static final int CUJ_AMBIENT_CUE_SHOW = 145; /** * Tracks hide animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI starts to hide (a user click the close button, switch * to another task, etc) and ends when cue bar UI disappears completely. */ public static final int CUJ_AMBIENT_CUE_HIDE = 146; /** * Tracks expand animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when a user click the cue bar to expand the action list and ends then all * actions show. */ public static final int CUJ_AMBIENT_CUE_EXPAND = 147; /** * Tracks collapse animation for Cue bar. Cue bar is a floating bar that appears on the screen * to provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI tap other region to collapse the action list and ends * when action list disappear completely. */ public static final int CUJ_AMBIENT_CUE_COLLAPSE = 148; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN; @VisibleForTesting static final int LAST_CUJ = CUJ_AMBIENT_CUE_COLLAPSE; /** @hide */ @IntDef({ Loading Loading @@ -614,6 +650,10 @@ public class Cuj { CUJ_LAUNCHER_WIDGET_PICKER_APP_EXPAND, CUJ_DESKTOP_MODE_MOVE_TO_SPLIT_SCREEN, CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN, CUJ_AMBIENT_CUE_SHOW, CUJ_AMBIENT_CUE_HIDE, CUJ_AMBIENT_CUE_EXPAND, CUJ_AMBIENT_CUE_COLLAPSE, }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -1044,6 +1084,14 @@ public class Cuj { return "DESKTOP_MODE_MOVE_TO_SPLIT_SCREEN"; case CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN: return "DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN"; case CUJ_AMBIENT_CUE_SHOW: return "AMBIENT_CUE_SHOW"; case CUJ_AMBIENT_CUE_HIDE: return "AMBIENT_CUE_HIDE"; case CUJ_AMBIENT_CUE_EXPAND: return "AMBIENT_CUE_EXPAND"; case CUJ_AMBIENT_CUE_COLLAPSE: return "AMBIENT_CUE_COLLAPSE"; } return "UNKNOWN"; } Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +8 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toSize import com.android.compose.windowsizeclass.calculateWindowSizeClass import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel import com.android.systemui.ambientcue.ui.viewmodel.AmbientCueViewModel import com.android.systemui.ambientcue.ui.viewmodel.PillStyleViewModel Loading @@ -57,6 +58,7 @@ fun AmbientCueContainer( ambientCueViewModelFactory: AmbientCueViewModel.Factory, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val viewModel = rememberViewModel("AmbientCueContainer") { ambientCueViewModelFactory.create() } Loading Loading @@ -89,6 +91,7 @@ fun AmbientCueContainer( expanded = expanded, onShouldInterceptTouches = onShouldInterceptTouches, modifier = Modifier.align(Alignment.BottomCenter), onAnimationStateChange = onAnimationStateChange, ) } is PillStyleViewModel.ShortPillStyle -> { Loading @@ -106,6 +109,7 @@ fun AmbientCueContainer( } else { Modifier }, onAnimationStateChange = onAnimationStateChange, ) } is PillStyleViewModel.Uninitialized -> {} Loading @@ -122,6 +126,7 @@ private fun TaskBarAnd3ButtonAmbientCue( pillPositionInWindow: Rect?, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val configuration = LocalConfiguration.current val density = LocalDensity.current Loading Loading @@ -216,6 +221,7 @@ private fun TaskBarAnd3ButtonAmbientCue( }, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, onAnimationStateChange = onAnimationStateChange, ) } Loading @@ -227,6 +233,7 @@ private fun NavBarAmbientCue( expanded: Boolean, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val windowWidthSizeClass = calculateWindowSizeClass().widthSizeClass Loading Loading @@ -271,6 +278,7 @@ private fun NavBarAmbientCue( }, onCloseClick = { viewModel.hide() }, onCloseEducation = { viewModel.disableFirstTimeHint() }, onAnimationStateChange = onAnimationStateChange, ) } Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueJankMonitorComposable.kt 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.ambientcue.ui.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import com.android.internal.jank.Cuj import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState @Composable fun AmbientCueJankMonitorComposable( visibleTargetState: Boolean, enterProgress: Float, expanded: Boolean, expansionAlpha: Float, showAnimationInProgress: MutableState<Boolean>, hideAnimationInProgress: MutableState<Boolean>, expandAnimationInProgress: MutableState<Boolean>, collapseAnimationInProgress: MutableState<Boolean>, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { LaunchedEffect(visibleTargetState, enterProgress) { if (visibleTargetState) { when (enterProgress) { 0f -> { showAnimationInProgress.value = true onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.BEGIN) } 1f -> { showAnimationInProgress.value = false onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.END) } } } else { when (enterProgress) { 0f -> { hideAnimationInProgress.value = false onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.END) } 1f -> { hideAnimationInProgress.value = true onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.BEGIN) } } } } LaunchedEffect(expanded, expansionAlpha) { if (expanded) { when (expansionAlpha) { 0f -> { if (expandAnimationInProgress.value) { expandAnimationInProgress.value = false onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.END, ) } } 1f -> { expandAnimationInProgress.value = true onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.BEGIN, ) } } } else { when (expansionAlpha) { 0f -> { collapseAnimationInProgress.value = true onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.BEGIN, ) } 1f -> { if (collapseAnimationInProgress.value) { collapseAnimationInProgress.value = false onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.END, ) } } } } } DisposableEffect(Unit) { onDispose { if (showAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.CANCEL) } if (hideAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.CANCEL) } if (expandAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.CANCEL) } if (collapseAnimationInProgress.value) { onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.CANCEL, ) } } } } packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/NavBarPill.kt +17 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.lerp import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.systemui.ambientcue.ui.compose.modifier.animatedActionBorder import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.utils.FilterUtils import com.android.systemui.ambientcue.ui.viewmodel.ActionType import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel Loading @@ -95,6 +96,7 @@ fun NavBarPill( onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, onCloseEducation: () -> Unit = {}, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit = { _, _ -> }, ) { val maxPillWidth = 248.dp val backgroundColor = if (isSystemInDarkTheme()) Color.Black else Color.White Loading @@ -103,6 +105,10 @@ fun NavBarPill( val density = LocalDensity.current val collapsedWidthPx = with(density) { navBarWidth.toPx() } var wasEverCollapsed by remember(actions) { mutableStateOf(false) } val showAnimationInProgress = remember { mutableStateOf(false) } val hideAnimationInProgress = remember { mutableStateOf(false) } val expandAnimationInProgress = remember { mutableStateOf(false) } val collapseAnimationInProgress = remember { mutableStateOf(false) } LaunchedEffect(expanded) { if (expanded) { wasEverCollapsed = true Loading Loading @@ -156,6 +162,17 @@ fun NavBarPill( animationSpec = tween(250, delayMillis = 200), label = "smartScrimOffset", ) AmbientCueJankMonitorComposable( visibleTargetState = visibleState.targetState, enterProgress = enterProgress, expanded = expanded, expansionAlpha = expansionAlpha, showAnimationInProgress = showAnimationInProgress, hideAnimationInProgress = hideAnimationInProgress, expandAnimationInProgress = expandAnimationInProgress, collapseAnimationInProgress = collapseAnimationInProgress, onAnimationStateChange = onAnimationStateChange, ) val config = LocalConfiguration.current val isBoldTextEnabled = config.fontWeightAdjustment > 0 Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ShortPill.kt +18 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.systemui.ambientcue.ui.compose.modifier.animatedActionBorder import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.utils.FilterUtils import com.android.systemui.ambientcue.ui.viewmodel.ActionType import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel Loading @@ -91,6 +92,7 @@ fun ShortPill( rotation: Int = 0, onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit = { _, _ -> }, ) { val outlineColor = if (isSystemInDarkTheme()) Color.White else Color.Black val backgroundColor = if (isSystemInDarkTheme()) Color.Black else Color.White Loading @@ -101,6 +103,10 @@ fun ShortPill( val shortPillBoxWidth = 48.dp val shortPillBoxLength = 68.dp val transitionTween: TweenSpec<Float> = tween(250, delayMillis = 200) val showAnimationInProgress = remember { mutableStateOf(false) } val hideAnimationInProgress = remember { mutableStateOf(false) } val expandAnimationInProgress = remember { mutableStateOf(false) } val collapseAnimationInProgress = remember { mutableStateOf(false) } val visibleState = remember { MutableTransitionState(false) } visibleState.targetState = visible Loading Loading @@ -140,6 +146,18 @@ fun ShortPill( if (it) 0.4f else 0f } AmbientCueJankMonitorComposable( visibleTargetState = visibleState.targetState, enterProgress = enterProgress, expanded = expanded, expansionAlpha = expansionAlpha, showAnimationInProgress = showAnimationInProgress, hideAnimationInProgress = hideAnimationInProgress, expandAnimationInProgress = expandAnimationInProgress, collapseAnimationInProgress = collapseAnimationInProgress, onAnimationStateChange = onAnimationStateChange, ) // State variables to store the measured size and position of the main pill. var pillContentSize by remember { mutableStateOf(IntSize.Zero) } var pillContentPosition by remember { mutableStateOf(Offset.Zero) } Loading Loading
core/java/com/android/internal/jank/Cuj.java +49 −1 Original line number Diff line number Diff line Loading @@ -476,8 +476,44 @@ public class Cuj { */ public static final int CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN = 144; /** * Tracks show animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI starts to show and ends when cue bar UI show * completely. */ public static final int CUJ_AMBIENT_CUE_SHOW = 145; /** * Tracks hide animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI starts to hide (a user click the close button, switch * to another task, etc) and ends when cue bar UI disappears completely. */ public static final int CUJ_AMBIENT_CUE_HIDE = 146; /** * Tracks expand animation for Cue bar. Cue bar is a floating bar that appears on the screen to * provide personalized contextual actions based on the current app. * * <p>Tracking begins when a user click the cue bar to expand the action list and ends then all * actions show. */ public static final int CUJ_AMBIENT_CUE_EXPAND = 147; /** * Tracks collapse animation for Cue bar. Cue bar is a floating bar that appears on the screen * to provide personalized contextual actions based on the current app. * * <p>Tracking begins when the cue bar UI tap other region to collapse the action list and ends * when action list disappear completely. */ public static final int CUJ_AMBIENT_CUE_COLLAPSE = 148; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN; @VisibleForTesting static final int LAST_CUJ = CUJ_AMBIENT_CUE_COLLAPSE; /** @hide */ @IntDef({ Loading Loading @@ -614,6 +650,10 @@ public class Cuj { CUJ_LAUNCHER_WIDGET_PICKER_APP_EXPAND, CUJ_DESKTOP_MODE_MOVE_TO_SPLIT_SCREEN, CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN, CUJ_AMBIENT_CUE_SHOW, CUJ_AMBIENT_CUE_HIDE, CUJ_AMBIENT_CUE_EXPAND, CUJ_AMBIENT_CUE_COLLAPSE, }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -1044,6 +1084,14 @@ public class Cuj { return "DESKTOP_MODE_MOVE_TO_SPLIT_SCREEN"; case CUJ_DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN: return "DESKTOP_MODE_MOVE_FROM_SPLIT_SCREEN"; case CUJ_AMBIENT_CUE_SHOW: return "AMBIENT_CUE_SHOW"; case CUJ_AMBIENT_CUE_HIDE: return "AMBIENT_CUE_HIDE"; case CUJ_AMBIENT_CUE_EXPAND: return "AMBIENT_CUE_EXPAND"; case CUJ_AMBIENT_CUE_COLLAPSE: return "AMBIENT_CUE_COLLAPSE"; } return "UNKNOWN"; } Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +8 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toSize import com.android.compose.windowsizeclass.calculateWindowSizeClass import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel import com.android.systemui.ambientcue.ui.viewmodel.AmbientCueViewModel import com.android.systemui.ambientcue.ui.viewmodel.PillStyleViewModel Loading @@ -57,6 +58,7 @@ fun AmbientCueContainer( ambientCueViewModelFactory: AmbientCueViewModel.Factory, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val viewModel = rememberViewModel("AmbientCueContainer") { ambientCueViewModelFactory.create() } Loading Loading @@ -89,6 +91,7 @@ fun AmbientCueContainer( expanded = expanded, onShouldInterceptTouches = onShouldInterceptTouches, modifier = Modifier.align(Alignment.BottomCenter), onAnimationStateChange = onAnimationStateChange, ) } is PillStyleViewModel.ShortPillStyle -> { Loading @@ -106,6 +109,7 @@ fun AmbientCueContainer( } else { Modifier }, onAnimationStateChange = onAnimationStateChange, ) } is PillStyleViewModel.Uninitialized -> {} Loading @@ -122,6 +126,7 @@ private fun TaskBarAnd3ButtonAmbientCue( pillPositionInWindow: Rect?, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val configuration = LocalConfiguration.current val density = LocalDensity.current Loading Loading @@ -216,6 +221,7 @@ private fun TaskBarAnd3ButtonAmbientCue( }, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, onAnimationStateChange = onAnimationStateChange, ) } Loading @@ -227,6 +233,7 @@ private fun NavBarAmbientCue( expanded: Boolean, onShouldInterceptTouches: (Boolean, Rect?) -> Unit, modifier: Modifier = Modifier, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { val windowWidthSizeClass = calculateWindowSizeClass().widthSizeClass Loading Loading @@ -271,6 +278,7 @@ private fun NavBarAmbientCue( }, onCloseClick = { viewModel.hide() }, onCloseEducation = { viewModel.disableFirstTimeHint() }, onAnimationStateChange = onAnimationStateChange, ) } Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueJankMonitorComposable.kt 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.ambientcue.ui.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import com.android.internal.jank.Cuj import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState @Composable fun AmbientCueJankMonitorComposable( visibleTargetState: Boolean, enterProgress: Float, expanded: Boolean, expansionAlpha: Float, showAnimationInProgress: MutableState<Boolean>, hideAnimationInProgress: MutableState<Boolean>, expandAnimationInProgress: MutableState<Boolean>, collapseAnimationInProgress: MutableState<Boolean>, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit, ) { LaunchedEffect(visibleTargetState, enterProgress) { if (visibleTargetState) { when (enterProgress) { 0f -> { showAnimationInProgress.value = true onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.BEGIN) } 1f -> { showAnimationInProgress.value = false onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.END) } } } else { when (enterProgress) { 0f -> { hideAnimationInProgress.value = false onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.END) } 1f -> { hideAnimationInProgress.value = true onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.BEGIN) } } } } LaunchedEffect(expanded, expansionAlpha) { if (expanded) { when (expansionAlpha) { 0f -> { if (expandAnimationInProgress.value) { expandAnimationInProgress.value = false onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.END, ) } } 1f -> { expandAnimationInProgress.value = true onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.BEGIN, ) } } } else { when (expansionAlpha) { 0f -> { collapseAnimationInProgress.value = true onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.BEGIN, ) } 1f -> { if (collapseAnimationInProgress.value) { collapseAnimationInProgress.value = false onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.END, ) } } } } } DisposableEffect(Unit) { onDispose { if (showAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_SHOW, AmbientCueAnimationState.CANCEL) } if (hideAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_HIDE, AmbientCueAnimationState.CANCEL) } if (expandAnimationInProgress.value) { onAnimationStateChange(Cuj.CUJ_AMBIENT_CUE_EXPAND, AmbientCueAnimationState.CANCEL) } if (collapseAnimationInProgress.value) { onAnimationStateChange( Cuj.CUJ_AMBIENT_CUE_COLLAPSE, AmbientCueAnimationState.CANCEL, ) } } } }
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/NavBarPill.kt +17 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.lerp import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.systemui.ambientcue.ui.compose.modifier.animatedActionBorder import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.utils.FilterUtils import com.android.systemui.ambientcue.ui.viewmodel.ActionType import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel Loading @@ -95,6 +96,7 @@ fun NavBarPill( onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, onCloseEducation: () -> Unit = {}, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit = { _, _ -> }, ) { val maxPillWidth = 248.dp val backgroundColor = if (isSystemInDarkTheme()) Color.Black else Color.White Loading @@ -103,6 +105,10 @@ fun NavBarPill( val density = LocalDensity.current val collapsedWidthPx = with(density) { navBarWidth.toPx() } var wasEverCollapsed by remember(actions) { mutableStateOf(false) } val showAnimationInProgress = remember { mutableStateOf(false) } val hideAnimationInProgress = remember { mutableStateOf(false) } val expandAnimationInProgress = remember { mutableStateOf(false) } val collapseAnimationInProgress = remember { mutableStateOf(false) } LaunchedEffect(expanded) { if (expanded) { wasEverCollapsed = true Loading Loading @@ -156,6 +162,17 @@ fun NavBarPill( animationSpec = tween(250, delayMillis = 200), label = "smartScrimOffset", ) AmbientCueJankMonitorComposable( visibleTargetState = visibleState.targetState, enterProgress = enterProgress, expanded = expanded, expansionAlpha = expansionAlpha, showAnimationInProgress = showAnimationInProgress, hideAnimationInProgress = hideAnimationInProgress, expandAnimationInProgress = expandAnimationInProgress, collapseAnimationInProgress = collapseAnimationInProgress, onAnimationStateChange = onAnimationStateChange, ) val config = LocalConfiguration.current val isBoldTextEnabled = config.fontWeightAdjustment > 0 Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ShortPill.kt +18 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.systemui.ambientcue.ui.compose.modifier.animatedActionBorder import com.android.systemui.ambientcue.ui.utils.AmbientCueAnimationState import com.android.systemui.ambientcue.ui.utils.FilterUtils import com.android.systemui.ambientcue.ui.viewmodel.ActionType import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel Loading @@ -91,6 +92,7 @@ fun ShortPill( rotation: Int = 0, onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, onAnimationStateChange: (Int, AmbientCueAnimationState) -> Unit = { _, _ -> }, ) { val outlineColor = if (isSystemInDarkTheme()) Color.White else Color.Black val backgroundColor = if (isSystemInDarkTheme()) Color.Black else Color.White Loading @@ -101,6 +103,10 @@ fun ShortPill( val shortPillBoxWidth = 48.dp val shortPillBoxLength = 68.dp val transitionTween: TweenSpec<Float> = tween(250, delayMillis = 200) val showAnimationInProgress = remember { mutableStateOf(false) } val hideAnimationInProgress = remember { mutableStateOf(false) } val expandAnimationInProgress = remember { mutableStateOf(false) } val collapseAnimationInProgress = remember { mutableStateOf(false) } val visibleState = remember { MutableTransitionState(false) } visibleState.targetState = visible Loading Loading @@ -140,6 +146,18 @@ fun ShortPill( if (it) 0.4f else 0f } AmbientCueJankMonitorComposable( visibleTargetState = visibleState.targetState, enterProgress = enterProgress, expanded = expanded, expansionAlpha = expansionAlpha, showAnimationInProgress = showAnimationInProgress, hideAnimationInProgress = hideAnimationInProgress, expandAnimationInProgress = expandAnimationInProgress, collapseAnimationInProgress = collapseAnimationInProgress, onAnimationStateChange = onAnimationStateChange, ) // State variables to store the measured size and position of the main pill. var pillContentSize by remember { mutableStateOf(IntSize.Zero) } var pillContentPosition by remember { mutableStateOf(Offset.Zero) } Loading