Loading packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java +11 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.LifecycleOwner; import com.android.settingslib.widget.SettingsThemeHelper; /** * {@link Activity} that has hooks to observe activity lifecycle events. */ Loading @@ -49,6 +51,7 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn mLifecycle.onCreate(savedInstanceState); mLifecycle.handleLifecycleEvent(ON_CREATE); super.onCreate(savedInstanceState); updateTheme(); } @Override Loading @@ -58,6 +61,7 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn mLifecycle.onCreate(savedInstanceState); mLifecycle.handleLifecycleEvent(ON_CREATE); super.onCreate(savedInstanceState, persistentState); updateTheme(); } @Override Loading Loading @@ -116,4 +120,11 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn } return lifecycleHandled; } private void updateTheme() { int resId = SettingsThemeHelper.isExpressiveTheme(this) ? com.android.settingslib.widget.theme.R.style.Theme_SubSettingsBase_Expressive : com.android.settingslib.widget.theme.R.style.Theme_SubSettingsBase; setTheme(resId); } } packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +1 −1 Original line number Diff line number Diff line Loading @@ -2130,7 +2130,7 @@ public class SettingsProvider extends ContentProvider { } case MUTATION_OPERATION_RESET -> { success = mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SYSTEM, runAsUserId, callingDeviceId, callingPackage, mode, tag); owningUserId, callingDeviceId, callingPackage, mode, tag); } default -> { success = false; Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ActionList.kt +8 −4 Original line number Diff line number Diff line Loading @@ -31,18 +31,22 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel @Composable fun ActionList(actions: List<ActionViewModel>, visible: Boolean, modifier: Modifier = Modifier) { fun ActionList( actions: List<ActionViewModel>, visible: Boolean, modifier: Modifier = Modifier, horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, ) { val density = LocalDensity.current Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = horizontalAlignment, ) { actions.fastForEachIndexed { index, action -> actions.forEachIndexed { index, action -> AnimatedVisibility( visible = visible, enter = Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +118 −22 Original line number Diff line number Diff line Loading @@ -16,17 +16,34 @@ package com.android.systemui.ambientcue.ui.compose import android.content.res.Configuration import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.boundsInParent import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel import com.android.systemui.ambientcue.ui.viewmodel.AmbientCueViewModel import com.android.systemui.ambientcue.ui.viewmodel.PillStyleViewModel import com.android.systemui.lifecycle.rememberViewModel // TODO: b/414507396 - Replace with the height of the navbar private val chipsBottomPadding = 46.dp @Composable fun AmbientCueContainer( modifier: Modifier = Modifier, Loading @@ -38,9 +55,7 @@ fun AmbientCueContainer( val visible = viewModel.isVisible val expanded = viewModel.isExpanded val actions = viewModel.actions // TODO: b/414507396 - Replace with the height of the navbar val chipsBottomPadding = 46.dp val pillStyle = viewModel.pillStyle LaunchedEffect(expanded) { onShouldInterceptTouches(expanded) Loading @@ -58,24 +73,105 @@ fun AmbientCueContainer( viewModel.collapse() } ) { BackgroundGlow( when (pillStyle) { is PillStyleViewModel.NavBarPillStyle -> { NavBarAmbientCue( viewModel = viewModel, actions = actions, visible = visible, expanded = expanded, modifier = Modifier.align(Alignment.BottomCenter), ) } is PillStyleViewModel.ShortPillStyle -> { val pillCenterInWindow = pillStyle.position TaskBarAnd3ButtonAmbientCue( viewModel = viewModel, actions = actions, visible = visible, expanded = expanded, pillCenterInWindow = pillCenterInWindow, modifier = if (pillCenterInWindow == null) { Modifier.align(Alignment.BottomCenter) } else { Modifier }, ) } is PillStyleViewModel.Uninitialized -> {} } } } @Composable private fun TaskBarAnd3ButtonAmbientCue( viewModel: AmbientCueViewModel, actions: List<ActionViewModel>, visible: Boolean, expanded: Boolean, pillCenterInWindow: Rect?, modifier: Modifier = Modifier, ) { val configuration = LocalConfiguration.current val portrait = configuration.orientation == Configuration.ORIENTATION_PORTRAIT var pillCenter by remember { mutableStateOf(Offset.Zero) } BackgroundGlow( visible = visible, expanded = expanded, collapsedOffset = IntOffset(0, 110), modifier = modifier.graphicsLayer { translationX = -size.width / 2 + pillCenter.x }, ) ShortPill( actions = actions, visible = visible, horizontal = portrait, expanded = expanded, modifier = if (pillCenterInWindow == null) { modifier.padding(bottom = 12.dp, end = 24.dp).onGloballyPositioned { pillCenter = it.boundsInParent().center } } else { Modifier.graphicsLayer { val center = pillCenterInWindow.center translationX = center.x - size.width / 2 translationY = center.y - size.height / 2 pillCenter = center } }, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, ) ActionList( actions = actions, visible = visible && expanded, horizontalAlignment = Alignment.End, modifier = modifier.padding(bottom = chipsBottomPadding, end = 24.dp), ) } @Composable private fun NavBarAmbientCue( viewModel: AmbientCueViewModel, actions: List<ActionViewModel>, visible: Boolean, expanded: Boolean, modifier: Modifier = Modifier, ) { BackgroundGlow(visible = visible, expanded = expanded, modifier = modifier) NavBarPill( actions = actions, navBarWidth = 110.dp, // TODO: b/414507396 - Replace with the width of the navbar visible = visible, expanded = expanded, modifier = Modifier.align(Alignment.BottomCenter), modifier = modifier, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, ) ActionList( actions = actions, visible = visible && expanded, modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = chipsBottomPadding), modifier = modifier.padding(bottom = chipsBottomPadding), ) } } packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/BackgroundGlow.kt +12 −6 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.android.systemui.ambientcue.ui.compose import android.graphics.RuntimeShader import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateIntOffsetAsState import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween Loading @@ -37,20 +37,25 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.systemui.ambientcue.ui.shader.BackgroundGlowShader import com.android.systemui.ambientcue.ui.utils.AiColorUtils.boostChroma @Composable fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { fun BackgroundGlow( visible: Boolean, expanded: Boolean, collapsedOffset: IntOffset = IntOffset(0, 110), modifier: Modifier, ) { val density = LocalDensity.current val turbulenceDisplacementPx = with(density) { Defaults.TURBULENCE_DISPLACEMENT_DP.dp.toPx() } val gradientRadiusPx = with(density) { Defaults.GRADIENT_RADIUS.dp.toPx() } val alpha by animateFloatAsState(if (visible) 1f else 0f, animationSpec = tween(750)) val verticalOffset by animateDpAsState(if (expanded) 0.dp else Defaults.COLLAPSED_TRANSLATION_DP.dp, tween(350)) val verticalOffsetPx = with(density) { verticalOffset.toPx() } animateIntOffsetAsState(if (expanded) IntOffset.Zero else collapsedOffset, tween(350)) // Infinite animation responsible for the "vapor" effect distorting the radial gradient val infiniteTransition = rememberInfiniteTransition(label = "backgroundGlow") Loading @@ -76,12 +81,14 @@ fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { Box( modifier.size(400.dp, 200.dp).alpha(alpha).drawWithCache { onDrawWithContent { val offsetX = with(density) { verticalOffset.x.dp.toPx() } val offsetY = with(density) { verticalOffset.y.dp.toPx() } shader.setFloatUniform("alpha", alpha) shader.setFloatUniform("resolution", size.width, size.height) shader.setColorUniform("color1", color1.toArgb()) shader.setColorUniform("color2", color2.toArgb()) shader.setColorUniform("color3", color3.toArgb()) shader.setFloatUniform("origin", size.width / 2, size.height + verticalOffsetPx) shader.setFloatUniform("origin", size.width / 2 + offsetX, size.height + offsetY) shader.setFloatUniform("radius", gradientRadiusPx) shader.setFloatUniform("turbulenceAmount", turbulenceDisplacementPx) shader.setFloatUniform("turbulencePhase", turbulencePhase) Loading @@ -93,7 +100,6 @@ fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { } private object Defaults { const val COLLAPSED_TRANSLATION_DP = 110 const val TURBULENCE_SIZE = 4.7f const val TURBULENCE_DISPLACEMENT_DP = 30 const val GRADIENT_RADIUS = 200 Loading Loading
packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java +11 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.LifecycleOwner; import com.android.settingslib.widget.SettingsThemeHelper; /** * {@link Activity} that has hooks to observe activity lifecycle events. */ Loading @@ -49,6 +51,7 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn mLifecycle.onCreate(savedInstanceState); mLifecycle.handleLifecycleEvent(ON_CREATE); super.onCreate(savedInstanceState); updateTheme(); } @Override Loading @@ -58,6 +61,7 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn mLifecycle.onCreate(savedInstanceState); mLifecycle.handleLifecycleEvent(ON_CREATE); super.onCreate(savedInstanceState, persistentState); updateTheme(); } @Override Loading Loading @@ -116,4 +120,11 @@ public class ObservableActivity extends FragmentActivity implements LifecycleOwn } return lifecycleHandled; } private void updateTheme() { int resId = SettingsThemeHelper.isExpressiveTheme(this) ? com.android.settingslib.widget.theme.R.style.Theme_SubSettingsBase_Expressive : com.android.settingslib.widget.theme.R.style.Theme_SubSettingsBase; setTheme(resId); } }
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +1 −1 Original line number Diff line number Diff line Loading @@ -2130,7 +2130,7 @@ public class SettingsProvider extends ContentProvider { } case MUTATION_OPERATION_RESET -> { success = mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SYSTEM, runAsUserId, callingDeviceId, callingPackage, mode, tag); owningUserId, callingDeviceId, callingPackage, mode, tag); } default -> { success = false; Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ActionList.kt +8 −4 Original line number Diff line number Diff line Loading @@ -31,18 +31,22 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel @Composable fun ActionList(actions: List<ActionViewModel>, visible: Boolean, modifier: Modifier = Modifier) { fun ActionList( actions: List<ActionViewModel>, visible: Boolean, modifier: Modifier = Modifier, horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, ) { val density = LocalDensity.current Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = horizontalAlignment, ) { actions.fastForEachIndexed { index, action -> actions.forEachIndexed { index, action -> AnimatedVisibility( visible = visible, enter = Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/AmbientCueContainer.kt +118 −22 Original line number Diff line number Diff line Loading @@ -16,17 +16,34 @@ package com.android.systemui.ambientcue.ui.compose import android.content.res.Configuration import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.boundsInParent import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.systemui.ambientcue.ui.viewmodel.ActionViewModel import com.android.systemui.ambientcue.ui.viewmodel.AmbientCueViewModel import com.android.systemui.ambientcue.ui.viewmodel.PillStyleViewModel import com.android.systemui.lifecycle.rememberViewModel // TODO: b/414507396 - Replace with the height of the navbar private val chipsBottomPadding = 46.dp @Composable fun AmbientCueContainer( modifier: Modifier = Modifier, Loading @@ -38,9 +55,7 @@ fun AmbientCueContainer( val visible = viewModel.isVisible val expanded = viewModel.isExpanded val actions = viewModel.actions // TODO: b/414507396 - Replace with the height of the navbar val chipsBottomPadding = 46.dp val pillStyle = viewModel.pillStyle LaunchedEffect(expanded) { onShouldInterceptTouches(expanded) Loading @@ -58,24 +73,105 @@ fun AmbientCueContainer( viewModel.collapse() } ) { BackgroundGlow( when (pillStyle) { is PillStyleViewModel.NavBarPillStyle -> { NavBarAmbientCue( viewModel = viewModel, actions = actions, visible = visible, expanded = expanded, modifier = Modifier.align(Alignment.BottomCenter), ) } is PillStyleViewModel.ShortPillStyle -> { val pillCenterInWindow = pillStyle.position TaskBarAnd3ButtonAmbientCue( viewModel = viewModel, actions = actions, visible = visible, expanded = expanded, pillCenterInWindow = pillCenterInWindow, modifier = if (pillCenterInWindow == null) { Modifier.align(Alignment.BottomCenter) } else { Modifier }, ) } is PillStyleViewModel.Uninitialized -> {} } } } @Composable private fun TaskBarAnd3ButtonAmbientCue( viewModel: AmbientCueViewModel, actions: List<ActionViewModel>, visible: Boolean, expanded: Boolean, pillCenterInWindow: Rect?, modifier: Modifier = Modifier, ) { val configuration = LocalConfiguration.current val portrait = configuration.orientation == Configuration.ORIENTATION_PORTRAIT var pillCenter by remember { mutableStateOf(Offset.Zero) } BackgroundGlow( visible = visible, expanded = expanded, collapsedOffset = IntOffset(0, 110), modifier = modifier.graphicsLayer { translationX = -size.width / 2 + pillCenter.x }, ) ShortPill( actions = actions, visible = visible, horizontal = portrait, expanded = expanded, modifier = if (pillCenterInWindow == null) { modifier.padding(bottom = 12.dp, end = 24.dp).onGloballyPositioned { pillCenter = it.boundsInParent().center } } else { Modifier.graphicsLayer { val center = pillCenterInWindow.center translationX = center.x - size.width / 2 translationY = center.y - size.height / 2 pillCenter = center } }, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, ) ActionList( actions = actions, visible = visible && expanded, horizontalAlignment = Alignment.End, modifier = modifier.padding(bottom = chipsBottomPadding, end = 24.dp), ) } @Composable private fun NavBarAmbientCue( viewModel: AmbientCueViewModel, actions: List<ActionViewModel>, visible: Boolean, expanded: Boolean, modifier: Modifier = Modifier, ) { BackgroundGlow(visible = visible, expanded = expanded, modifier = modifier) NavBarPill( actions = actions, navBarWidth = 110.dp, // TODO: b/414507396 - Replace with the width of the navbar visible = visible, expanded = expanded, modifier = Modifier.align(Alignment.BottomCenter), modifier = modifier, onClick = { viewModel.expand() }, onCloseClick = { viewModel.hide() }, ) ActionList( actions = actions, visible = visible && expanded, modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = chipsBottomPadding), modifier = modifier.padding(bottom = chipsBottomPadding), ) } }
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/BackgroundGlow.kt +12 −6 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.android.systemui.ambientcue.ui.compose import android.graphics.RuntimeShader import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateIntOffsetAsState import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween Loading @@ -37,20 +37,25 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.systemui.ambientcue.ui.shader.BackgroundGlowShader import com.android.systemui.ambientcue.ui.utils.AiColorUtils.boostChroma @Composable fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { fun BackgroundGlow( visible: Boolean, expanded: Boolean, collapsedOffset: IntOffset = IntOffset(0, 110), modifier: Modifier, ) { val density = LocalDensity.current val turbulenceDisplacementPx = with(density) { Defaults.TURBULENCE_DISPLACEMENT_DP.dp.toPx() } val gradientRadiusPx = with(density) { Defaults.GRADIENT_RADIUS.dp.toPx() } val alpha by animateFloatAsState(if (visible) 1f else 0f, animationSpec = tween(750)) val verticalOffset by animateDpAsState(if (expanded) 0.dp else Defaults.COLLAPSED_TRANSLATION_DP.dp, tween(350)) val verticalOffsetPx = with(density) { verticalOffset.toPx() } animateIntOffsetAsState(if (expanded) IntOffset.Zero else collapsedOffset, tween(350)) // Infinite animation responsible for the "vapor" effect distorting the radial gradient val infiniteTransition = rememberInfiniteTransition(label = "backgroundGlow") Loading @@ -76,12 +81,14 @@ fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { Box( modifier.size(400.dp, 200.dp).alpha(alpha).drawWithCache { onDrawWithContent { val offsetX = with(density) { verticalOffset.x.dp.toPx() } val offsetY = with(density) { verticalOffset.y.dp.toPx() } shader.setFloatUniform("alpha", alpha) shader.setFloatUniform("resolution", size.width, size.height) shader.setColorUniform("color1", color1.toArgb()) shader.setColorUniform("color2", color2.toArgb()) shader.setColorUniform("color3", color3.toArgb()) shader.setFloatUniform("origin", size.width / 2, size.height + verticalOffsetPx) shader.setFloatUniform("origin", size.width / 2 + offsetX, size.height + offsetY) shader.setFloatUniform("radius", gradientRadiusPx) shader.setFloatUniform("turbulenceAmount", turbulenceDisplacementPx) shader.setFloatUniform("turbulencePhase", turbulencePhase) Loading @@ -93,7 +100,6 @@ fun BackgroundGlow(visible: Boolean, expanded: Boolean, modifier: Modifier) { } private object Defaults { const val COLLAPSED_TRANSLATION_DP = 110 const val TURBULENCE_SIZE = 4.7f const val TURBULENCE_DISPLACEMENT_DP = 30 const val GRADIENT_RADIUS = 200 Loading