Merge "LockscreenShadeTransitionController: extract logic of keyguard and scrims" into tm-dev

This commit is contained in:
Christian Göllner
2022-04-01 14:10:21 +00:00
committed by Android (Google) Code Review
6 changed files with 309 additions and 108 deletions

View File

@@ -0,0 +1,61 @@
package com.android.systemui.statusbar
import android.content.Context
import android.content.res.Configuration
import android.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.LargeScreenUtils
import java.io.FileDescriptor
import java.io.PrintWriter
/** An abstract implementation of a class that controls the lockscreen to shade transition. */
abstract class AbstractLockscreenShadeTransitionController(
protected val context: Context,
configurationController: ConfigurationController,
dumpManager: DumpManager
) : Dumpable {
protected var useSplitShade = false
/**
* The amount of pixels that the user has dragged down during the shade transition on
* lockscreen.
*/
var dragDownAmount = 0f
set(value) {
if (value == field) {
return
}
field = value
onDragDownAmountChanged(value)
}
init {
updateResourcesInternal()
configurationController.addCallback(
object : ConfigurationController.ConfigurationListener {
override fun onConfigChanged(newConfig: Configuration?) {
updateResourcesInternal()
}
})
@Suppress("LeakingThis")
dumpManager.registerDumpable(this)
}
private fun updateResourcesInternal() {
useSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(context.resources)
updateResources()
}
protected abstract fun updateResources()
protected abstract fun onDragDownAmountChanged(dragDownAmount: Float)
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
dump(IndentingPrintWriter(pw, /* singleIndent= */ " "))
}
abstract fun dump(pw: IndentingPrintWriter)
}

View File

@@ -0,0 +1,120 @@
package com.android.systemui.statusbar
import android.content.Context
import android.util.IndentingPrintWriter
import android.util.MathUtils
import com.android.systemui.R
import com.android.systemui.dump.DumpManager
import com.android.systemui.media.MediaHierarchyManager
import com.android.systemui.statusbar.phone.NotificationPanelViewController
import com.android.systemui.statusbar.policy.ConfigurationController
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/** Controls the lockscreen to shade transition for the keyguard elements. */
class LockscreenShadeKeyguardTransitionController
@AssistedInject
constructor(
private val mediaHierarchyManager: MediaHierarchyManager,
@Assisted private val notificationPanelController: NotificationPanelViewController,
context: Context,
configurationController: ConfigurationController,
dumpManager: DumpManager
) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager) {
/**
* Distance that the full shade transition takes in order for the keyguard content on
* NotificationPanelViewController to fully fade (e.g. Clock & Smartspace).
*/
private var alphaTransitionDistance = 0
/**
* Distance that the full shade transition takes in order for the keyguard elements to fully
* translate into their final position
*/
private var keyguardTransitionDistance = 0
/** The amount of vertical offset for the keyguard during the full shade transition. */
private var keyguardTransitionOffset = 0
/** The amount of alpha that was last set on the keyguard elements. */
private var alpha = 0f
/** The latest progress [0,1] of the alpha transition. */
private var alphaProgress = 0f
/** The amount of alpha that was last set on the keyguard status bar. */
private var statusBarAlpha = 0f
/** The amount of translationY that was last set on the keyguard elements. */
private var translationY = 0
/** The latest progress [0,1] of the translationY progress. */
private var translationYProgress = 0f
override fun updateResources() {
alphaTransitionDistance =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
keyguardTransitionDistance =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_keyguard_transition_distance)
keyguardTransitionOffset =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_keyguard_transition_vertical_offset)
}
override fun onDragDownAmountChanged(dragDownAmount: Float) {
alphaProgress = MathUtils.saturate(dragDownAmount / alphaTransitionDistance)
alpha = 1f - alphaProgress
translationY = calculateKeyguardTranslationY(dragDownAmount)
notificationPanelController.setKeyguardTransitionProgress(alpha, translationY)
statusBarAlpha = if (useSplitShade) alpha else -1f
notificationPanelController.setKeyguardStatusBarAlpha(statusBarAlpha)
}
private fun calculateKeyguardTranslationY(dragDownAmount: Float): Int {
if (!useSplitShade) {
return 0
}
// On split-shade, the translationY of the keyguard should stay in sync with the
// translation of media.
if (mediaHierarchyManager.isCurrentlyInGuidedTransformation()) {
return mediaHierarchyManager.getGuidedTransformationTranslationY()
}
// When media is not showing, apply the default distance
translationYProgress = MathUtils.saturate(dragDownAmount / keyguardTransitionDistance)
val translationY = translationYProgress * keyguardTransitionOffset
return translationY.toInt()
}
override fun dump(indentingPrintWriter: IndentingPrintWriter) {
indentingPrintWriter.let {
it.println("LockscreenShadeKeyguardTransitionController:")
it.increaseIndent()
it.println("Resources:")
it.increaseIndent()
it.println("alphaTransitionDistance: $alphaTransitionDistance")
it.println("keyguardTransitionDistance: $keyguardTransitionDistance")
it.println("keyguardTransitionOffset: $keyguardTransitionOffset")
it.decreaseIndent()
it.println("State:")
it.increaseIndent()
it.println("dragDownAmount: $dragDownAmount")
it.println("alpha: $alpha")
it.println("alphaProgress: $alphaProgress")
it.println("statusBarAlpha: $statusBarAlpha")
it.println("translationProgress: $translationYProgress")
it.println("translationY: $translationY")
}
}
@AssistedFactory
fun interface Factory {
fun create(
notificationPanelController: NotificationPanelViewController
): LockscreenShadeKeyguardTransitionController
}
}

View File

@@ -0,0 +1,86 @@
package com.android.systemui.statusbar
import android.content.Context
import android.util.IndentingPrintWriter
import android.util.MathUtils
import com.android.systemui.R
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.policy.ConfigurationController
import javax.inject.Inject
/** Controls the lockscreen to shade transition for scrims. */
class LockscreenShadeScrimTransitionController
@Inject
constructor(
private val scrimController: ScrimController,
context: Context,
configurationController: ConfigurationController,
dumpManager: DumpManager
) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager) {
/**
* Distance that the full shade transition takes in order for scrim to fully transition to the
* shade (in alpha)
*/
private var scrimTransitionDistance = 0
/** Distance it takes in order for the notifications scrim fade in to start. */
private var notificationsScrimTransitionDelay = 0
/** Distance it takes for the notifications scrim to fully fade if after it started. */
private var notificationsScrimTransitionDistance = 0
/** The latest progress [0,1] the scrims transition. */
var scrimProgress = 0f
/** The latest progress [0,1] specifically of the notifications scrim transition. */
var notificationsScrimProgress = 0f
/**
* The last drag amount specifically for the notifications scrim. It is different to the normal
* [dragDownAmount] as the notifications scrim transition starts relative to the other scrims'
* progress.
*/
var notificationsScrimDragAmount = 0f
override fun updateResources() {
scrimTransitionDistance =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_scrim_transition_distance)
notificationsScrimTransitionDelay =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notifications_scrim_transition_delay)
notificationsScrimTransitionDistance =
context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notifications_scrim_transition_distance)
}
override fun onDragDownAmountChanged(dragDownAmount: Float) {
scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
notificationsScrimDragAmount = dragDownAmount - notificationsScrimTransitionDelay
notificationsScrimProgress =
MathUtils.saturate(notificationsScrimDragAmount / notificationsScrimTransitionDistance)
scrimController.setTransitionToFullShadeProgress(scrimProgress, notificationsScrimProgress)
}
override fun dump(indentingPrintWriter: IndentingPrintWriter) {
indentingPrintWriter.let {
it.println("LockscreenShadeScrimTransitionController:")
it.increaseIndent()
it.println("Resources:")
it.increaseIndent()
it.println("scrimTransitionDistance: $scrimTransitionDistance")
it.println("notificationsScrimTransitionDelay: $notificationsScrimTransitionDelay")
it.println(
"notificationsScrimTransitionDistance: $notificationsScrimTransitionDistance")
it.decreaseIndent()
it.println("State")
it.increaseIndent()
it.println("dragDownAmount: $dragDownAmount")
it.println("scrimProgress: $scrimProgress")
it.println("notificationsScrimProgress: $notificationsScrimProgress")
it.println("notificationsScrimDragAmount: $notificationsScrimDragAmount")
}
}
}

View File

@@ -38,7 +38,6 @@ import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.NotificationPanelViewController
import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.LargeScreenUtils
import java.io.FileDescriptor
@@ -61,7 +60,9 @@ class LockscreenShadeTransitionController @Inject constructor(
private val falsingCollector: FalsingCollector,
private val ambientState: AmbientState,
private val mediaHierarchyManager: MediaHierarchyManager,
private val scrimController: ScrimController,
private val scrimTransitionController: LockscreenShadeScrimTransitionController,
private val keyguardTransitionControllerFactory:
LockscreenShadeKeyguardTransitionController.Factory,
private val depthController: NotificationShadeDepthController,
private val context: Context,
private val splitShadeOverScrollerFactory: SplitShadeLockScreenOverScroller.Factory,
@@ -111,22 +112,6 @@ class LockscreenShadeTransitionController @Inject constructor(
*/
private var fullTransitionDistanceByTap = 0
/**
* Distance that the full shade transition takes in order for scrim to fully transition to the
* shade (in alpha)
*/
private var scrimTransitionDistance = 0
/**
* Distance that it takes in order for the notifications scrim fade in to start.
*/
private var notificationsScrimTransitionDelay = 0
/**
* Distance that it takes for the notifications scrim to fully fade if after it started.
*/
private var notificationsScrimTransitionDistance = 0
/**
* Distance that the full shade transition takes in order for the notification shelf to fully
* expand.
@@ -139,12 +124,6 @@ class LockscreenShadeTransitionController @Inject constructor(
*/
private var qsTransitionDistance = 0
/**
* Distance that the full shade transition takes in order for the keyguard content on
* NotificationPanelViewController to fully fade (e.g. Clock & Smartspace).
*/
private var npvcKeyguardContentAlphaTransitionDistance = 0
/**
* Distance that the full shade transition takes in order for depth of the wallpaper to fully
* change.
@@ -163,17 +142,6 @@ class LockscreenShadeTransitionController @Inject constructor(
*/
private var statusBarTransitionDistance = 0
/**
* Distance that the full shade transition takes in order for the keyguard elements to fully
* translate into their final position
*/
private var keyguardTransitionDistance = 0
/**
* The amount of vertical offset for the keyguard during the full shade transition.
*/
private var keyguardTransitionOffset = 0
/**
* Flag to make sure that the dragDownAmount is applied to the listeners even when in the
* locked down shade.
@@ -215,6 +183,10 @@ class LockscreenShadeTransitionController @Inject constructor(
singleShadeOverScrollerFactory.create(nsslController)
}
private val keyguardTransitionController by lazy {
keyguardTransitionControllerFactory.create(notificationPanelController)
}
/**
* [LockScreenShadeOverScroller] property that delegates to either
* [SingleShadeLockScreenOverScroller] or [SplitShadeLockScreenOverScroller].
@@ -267,18 +239,10 @@ class LockscreenShadeTransitionController @Inject constructor(
R.dimen.lockscreen_shade_full_transition_distance)
fullTransitionDistanceByTap = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_transition_by_tap_distance)
scrimTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_scrim_transition_distance)
notificationsScrimTransitionDelay = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notifications_scrim_transition_delay)
notificationsScrimTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notifications_scrim_transition_distance)
notificationShelfTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_notif_shelf_transition_distance)
qsTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_qs_transition_distance)
npvcKeyguardContentAlphaTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
depthControllerTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_depth_controller_transition_distance)
udfpsTransitionDistance = context.resources.getDimensionPixelSize(
@@ -286,10 +250,6 @@ class LockscreenShadeTransitionController @Inject constructor(
statusBarTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_status_bar_transition_distance)
useSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(context.resources)
keyguardTransitionDistance = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_keyguard_transition_distance)
keyguardTransitionOffset = context.resources.getDimensionPixelSize(
R.dimen.lockscreen_shade_keyguard_transition_vertical_offset)
}
fun setStackScroller(nsslController: NotificationStackScrollLayoutController) {
@@ -457,9 +417,9 @@ class LockscreenShadeTransitionController @Inject constructor(
false /* animate */, 0 /* delay */)
mediaHierarchyManager.setTransitionToFullShadeAmount(field)
transitionToShadeAmountScrim(field)
scrimTransitionController.dragDownAmount = value
transitionToShadeAmountCommon(field)
transitionToShadeAmountKeyguard(field)
keyguardTransitionController.dragDownAmount = value
shadeOverScroller.expansionDragDownAmount = dragDownAmount
}
}
@@ -471,14 +431,6 @@ class LockscreenShadeTransitionController @Inject constructor(
var qSDragProgress = 0f
private set
private fun transitionToShadeAmountScrim(dragDownAmount: Float) {
val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
val notificationsScrimDragAmount = dragDownAmount - notificationsScrimTransitionDelay
val notificationsScrimProgress = MathUtils.saturate(
notificationsScrimDragAmount / notificationsScrimTransitionDistance)
scrimController.setTransitionToFullShadeProgress(scrimProgress, notificationsScrimProgress)
}
private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
if (depthControllerTransitionDistance == 0) { // split shade
depthController.transitionToFullShadeProgress = 0f
@@ -495,34 +447,6 @@ class LockscreenShadeTransitionController @Inject constructor(
centralSurfaces.setTransitionToFullShadeProgress(statusBarProgress)
}
private fun transitionToShadeAmountKeyguard(dragDownAmount: Float) {
// Fade out all content only visible on the lockscreen
val keyguardAlphaProgress =
MathUtils.saturate(dragDownAmount / npvcKeyguardContentAlphaTransitionDistance)
val keyguardAlpha = 1f - keyguardAlphaProgress
val keyguardTranslationY = calculateKeyguardTranslationY(dragDownAmount)
notificationPanelController
.setKeyguardTransitionProgress(keyguardAlpha, keyguardTranslationY)
val statusBarAlpha = if (useSplitShade) keyguardAlpha else -1f
notificationPanelController.setKeyguardStatusBarAlpha(statusBarAlpha)
}
private fun calculateKeyguardTranslationY(dragDownAmount: Float): Int {
if (!useSplitShade) {
return 0
}
// On split-shade, the translationY of the keyguard should stay in sync with the
// translation of media.
if (mediaHierarchyManager.isCurrentlyInGuidedTransformation()) {
return mediaHierarchyManager.getGuidedTransformationTranslationY()
}
// When media is not showing, apply the default distance
val translationProgress = MathUtils.saturate(dragDownAmount / keyguardTransitionDistance)
val translationY = translationProgress * keyguardTransitionOffset
return translationY.toInt()
}
private fun setDragDownAmountAnimated(
target: Float,
delay: Long = 0,

View File

@@ -93,24 +93,34 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
.addOverride(R.bool.config_use_split_notification_shade, false)
context.getOrCreateTestableResources()
.addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
transitionController = LockscreenShadeTransitionController(
statusBarStateController = statusbarStateController,
logger = logger,
keyguardBypassController = keyguardBypassController,
lockScreenUserManager = lockScreenUserManager,
falsingCollector = falsingCollector,
ambientState = ambientState,
mediaHierarchyManager = mediaHierarchyManager,
scrimController = scrimController,
depthController = depthController,
wakefulnessLifecycle = wakefulnessLifecycle,
context = context,
configurationController = configurationController,
falsingManager = falsingManager,
dumpManager = dumpManager,
splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
singleShadeOverScrollerFactory = { singleShadeOverScroller }
)
transitionController =
LockscreenShadeTransitionController(
statusBarStateController = statusbarStateController,
logger = logger,
keyguardBypassController = keyguardBypassController,
lockScreenUserManager = lockScreenUserManager,
falsingCollector = falsingCollector,
ambientState = ambientState,
mediaHierarchyManager = mediaHierarchyManager,
depthController = depthController,
wakefulnessLifecycle = wakefulnessLifecycle,
context = context,
configurationController = configurationController,
falsingManager = falsingManager,
dumpManager = dumpManager,
splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
singleShadeOverScrollerFactory = { singleShadeOverScroller },
scrimTransitionController =
LockscreenShadeScrimTransitionController(
scrimController, context, configurationController, dumpManager),
keyguardTransitionControllerFactory = { notificationPanelController ->
LockscreenShadeKeyguardTransitionController(
mediaHierarchyManager,
notificationPanelController,
context,
configurationController,
dumpManager)
})
whenever(nsslController.view).thenReturn(stackscroller)
whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
transitionController.notificationPanelController = notificationPanelController

View File

@@ -5,22 +5,22 @@ import android.content.res.Configuration
/** Fake implementation of [ConfigurationController] for tests. */
class FakeConfigurationController : ConfigurationController {
private var listener: ConfigurationController.ConfigurationListener? = null
private var listeners = mutableListOf<ConfigurationController.ConfigurationListener>()
override fun addCallback(listener: ConfigurationController.ConfigurationListener) {
this.listener = listener
listeners += listener
}
override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
this.listener = null
listeners -= listener
}
override fun onConfigurationChanged(newConfiguration: Configuration?) {
listener?.onConfigChanged(newConfiguration)
listeners.forEach { it.onConfigChanged(newConfiguration) }
}
override fun notifyThemeChanged() {
listener?.onThemeChanged()
listeners.forEach { it.onThemeChanged() }
}
fun notifyConfigurationChanged() {