summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt2
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt88
8 files changed, 172 insertions, 35 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
index 3efdc5acb00c..4931b257ad18 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
@@ -192,4 +192,4 @@ class UnfoldMoveFromCenterAnimator @JvmOverloads constructor(
)
}
-private const val TRANSLATION_PERCENTAGE = 0.3f
+private const val TRANSLATION_PERCENTAGE = 0.08f
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index a2c91c7ca531..f68413ab715e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -694,6 +694,12 @@ object Flags {
val ENABLE_DARK_VIGNETTE_WHEN_FOLDING =
unreleasedFlag(2700, "enable_dark_vignette_when_folding")
+ // TODO(b/265764985): Tracking Bug
+ @Keep
+ @JvmField
+ val ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS =
+ unreleasedFlag(2701, "enable_unfold_status_bar_animations")
+
// TODO(b259590361): Tracking bug
val EXPERIMENTAL_FLAG = unreleasedFlag(2, "exp_flag_release")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 9a5d1b5514f5..62d302f2a592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -26,6 +26,8 @@ import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
@@ -215,6 +217,7 @@ class PhoneStatusBarViewController private constructor(
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
+ private val featureFlags: FeatureFlags,
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val shadeController: ShadeController,
@@ -224,17 +227,25 @@ class PhoneStatusBarViewController private constructor(
) {
fun create(
view: PhoneStatusBarView
- ) =
- PhoneStatusBarViewController(
- view,
- progressProvider.getOrNull(),
- centralSurfaces,
- shadeController,
- shadeLogger,
- unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
- userChipViewModel,
- viewUtil,
- configurationController
+ ): PhoneStatusBarViewController {
+ val statusBarMoveFromCenterAnimationController =
+ if (featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) {
+ unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController()
+ } else {
+ null
+ }
+
+ return PhoneStatusBarViewController(
+ view,
+ progressProvider.getOrNull(),
+ centralSurfaces,
+ shadeController,
+ shadeLogger,
+ statusBarMoveFromCenterAnimationController,
+ userChipViewModel,
+ viewUtil,
+ configurationController
)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
index 19a0866cd0a8..6f2ac2e5059a 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
@@ -87,6 +87,7 @@ constructor(
private var isFolded: Boolean = false
private var isUnfoldHandled: Boolean = true
private var overlayAddReason: AddOverlayReason? = null
+ private var isTouchBlocked: Boolean = true
private var currentRotation: Int = context.display!!.rotation
@@ -253,7 +254,15 @@ constructor(
params.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
params.fitInsetsTypes = 0
- params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+
+ val touchFlags =
+ if (isTouchBlocked) {
+ // Touchable by default, so it will block the touches
+ 0
+ } else {
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ }
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or touchFlags
params.setTrustedOverlay()
val packageName: String = context.opPackageName
@@ -262,6 +271,24 @@ constructor(
return params
}
+ private fun updateTouchBlockIfNeeded(progress: Float) {
+ // When unfolding unblock touches a bit earlier than the animation end as the
+ // interpolation has a long tail of very slight movement at the end which should not
+ // affect much the usage of the device
+ val shouldBlockTouches =
+ if (overlayAddReason == UNFOLD) {
+ progress < UNFOLD_BLOCK_TOUCHES_UNTIL_PROGRESS
+ } else {
+ true
+ }
+
+ if (isTouchBlocked != shouldBlockTouches) {
+ isTouchBlocked = shouldBlockTouches
+
+ traceSection("$TAG#relayoutToUpdateTouch") { root?.relayout(getLayoutParams()) }
+ }
+ }
+
private fun createLightRevealEffect(): LightRevealEffect {
val isVerticalFold =
currentRotation == Surface.ROTATION_0 || currentRotation == Surface.ROTATION_180
@@ -288,7 +315,10 @@ constructor(
private inner class TransitionListener : TransitionProgressListener {
override fun onTransitionProgress(progress: Float) {
- executeInBackground { scrimView?.revealAmount = calculateRevealAmount(progress) }
+ executeInBackground {
+ scrimView?.revealAmount = calculateRevealAmount(progress)
+ updateTouchBlockIfNeeded(progress)
+ }
}
override fun onTransitionFinished() {
@@ -360,5 +390,7 @@ constructor(
// constants for revealAmount.
const val TRANSPARENT = 1f
const val BLACK = 0f
+
+ private const val UNFOLD_BLOCK_TOUCHES_UNTIL_PROGRESS = 0.8f
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
index 6a68b71f639b..8841f481695d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
@@ -65,8 +65,8 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
// Positive translationX -> translated to the right
// 10x10 view center is 25px from the center,
// When progress is 0.5 it should be translated at:
- // 25 * 0.3 * (1 - 0.5) = 3.75px
- assertThat(view.translationX).isWithin(0.01f).of(3.75f)
+ // 25 * 0.08 * (1 - 0.5) = 1px
+ assertThat(view.translationX).isWithin(0.01f).of(1.0f)
}
@Test
@@ -81,8 +81,8 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
// Positive translationX -> translated to the right
// 10x10 view center is 25px from the center,
// When progress is 0 it should be translated at:
- // 25 * 0.3 * (1 - 0) = 7.5px
- assertThat(view.translationX).isWithin(0.01f).of(7.5f)
+ // 25 * 0.08 * (1 - 0) = 7.5px
+ assertThat(view.translationX).isWithin(0.01f).of(2f)
}
@Test
@@ -97,7 +97,7 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
// Positive translationX -> translated to the right
// 10x10 view center is 25px from the center,
// When progress is 1 it should be translated at:
- // 25 * 0.3 * 0 = 0px
+ // 25 * 0.08 * 0 = 0px
assertThat(view.translationX).isEqualTo(0f)
}
@@ -113,8 +113,8 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
// Positive translationX -> translated to the right, original translation is ignored
// 10x10 view center is 25px from the center,
// When progress is 0.5 it should be translated at:
- // 25 * 0.3 * (1 - 0.5) = 3.75px
- assertThat(view.translationX).isWithin(0.01f).of(3.75f)
+ // 25 * 0.08 * (1 - 0.5) = 1px
+ assertThat(view.translationX).isWithin(0.01f).of(1.0f)
}
@Test
@@ -154,7 +154,7 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
animator.onTransitionProgress(0.5f)
// Positive translationY -> translated to the bottom
- assertThat(view.translationY).isWithin(0.01f).of(3.75f)
+ assertThat(view.translationY).isWithin(0.01f).of(1f)
}
@Test
@@ -169,7 +169,7 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
animator.updateViewPositions()
// Negative translationX -> translated to the left
- assertThat(view.translationX).isWithin(0.1f).of(-5.25f)
+ assertThat(view.translationX).isWithin(0.1f).of(-1.4f)
}
private fun createView(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index cdc989897c8e..3edf33b9d3a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -25,6 +25,8 @@ import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.ShadeControllerImpl
import com.android.systemui.shade.ShadeLogger
@@ -34,6 +36,7 @@ import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -54,6 +57,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Mock
private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
+ private lateinit var featureFlags: FeatureFlags
+ @Mock
private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
@Mock
private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
@@ -93,6 +98,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
+ whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
+ .thenReturn(true)
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
unfoldConfig.isEnabled = true
@@ -108,6 +115,20 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
}
@Test
+ fun onViewAttachedAndDrawn_statusBarAnimationDisabled_animationNotInitialized() {
+ whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
+ .thenReturn(false)
+ val view = createViewMock()
+ unfoldConfig.isEnabled = true
+ // create the controller on main thread as it requires main looper
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ controller = createAndInitController(view)
+ }
+
+ verify(moveFromCenterAnimation, never()).onViewsReady(any())
+ }
+
+ @Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
val returnVal = view.onTouchEvent(
@@ -179,6 +200,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
return PhoneStatusBarViewController.Factory(
Optional.of(sysuiUnfoldComponent),
Optional.of(progressProvider),
+ featureFlags,
userChipViewModel,
centralSurfacesImpl,
shadeControllerImpl,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 0413d92b6abb..9fe2f5694dde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -40,7 +40,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
@Before
fun setUp() {
- progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider)
+ progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(context, foldStateProvider)
progressProvider.addCallback(listener)
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 28e493651137..f8f168bd4dc1 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -15,8 +15,15 @@
*/
package com.android.systemui.unfold.progress
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
+import android.content.Context
import android.os.Trace
+import android.util.FloatProperty
import android.util.Log
+import android.view.animation.AnimationUtils.loadInterpolator
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringAnimation
@@ -34,14 +41,22 @@ import com.android.systemui.unfold.updates.name
import javax.inject.Inject
/** Maps fold updates to unfold transition progress using DynamicAnimation. */
-class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
- private val foldStateProvider: FoldStateProvider
-) : UnfoldTransitionProgressProvider, FoldUpdatesListener, DynamicAnimation.OnAnimationEndListener {
+class PhysicsBasedUnfoldTransitionProgressProvider
+@Inject
+constructor(context: Context, private val foldStateProvider: FoldStateProvider) :
+ UnfoldTransitionProgressProvider, FoldUpdatesListener, DynamicAnimation.OnAnimationEndListener {
+
+ private val emphasizedInterpolator =
+ loadInterpolator(context, android.R.interpolator.fast_out_extra_slow_in)
+
+ private var cannedAnimator: ValueAnimator? = null
private val springAnimation =
- SpringAnimation(this, AnimationProgressProperty).apply {
- addEndListener(this@PhysicsBasedUnfoldTransitionProgressProvider)
- }
+ SpringAnimation(
+ this,
+ FloatPropertyCompat.createFloatPropertyCompat(AnimationProgressProperty)
+ )
+ .apply { addEndListener(this@PhysicsBasedUnfoldTransitionProgressProvider) }
private var isTransitionRunning = false
private var isAnimatedCancelRunning = false
@@ -76,7 +91,8 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
override fun onFoldUpdate(@FoldUpdate update: Int) {
when (update) {
- FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
+ FOLD_UPDATE_FINISH_FULL_OPEN,
+ FOLD_UPDATE_FINISH_HALF_OPEN -> {
// Do not cancel if we haven't started the transition yet.
// This could happen when we fully unfolded the device before the screen
// became available. In this case we start and immediately cancel the animation
@@ -100,6 +116,14 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
// the transition continues running.
if (isAnimatedCancelRunning) {
isAnimatedCancelRunning = false
+
+ // Switching to spring animation, start the animation if it
+ // is not running already
+ springAnimation.animateToFinalPosition(1.0f)
+
+ cannedAnimator?.removeAllListeners()
+ cannedAnimator?.cancel()
+ cannedAnimator = null
}
} else {
startTransition(startValue = 1f)
@@ -130,13 +154,22 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
}
isAnimatedCancelRunning = true
- springAnimation.animateToFinalPosition(endValue)
+
+ if (USE_CANNED_ANIMATION) {
+ startCannedCancelAnimation()
+ } else {
+ springAnimation.animateToFinalPosition(endValue)
+ }
} else {
transitionProgress = endValue
isAnimatedCancelRunning = false
isTransitionRunning = false
springAnimation.cancel()
+ cannedAnimator?.removeAllListeners()
+ cannedAnimator?.cancel()
+ cannedAnimator = null
+
listeners.forEach { it.onTransitionFinished() }
if (DEBUG) {
@@ -157,7 +190,7 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
}
private fun onStartTransition() {
- Trace.beginSection( "$TAG#onStartTransition")
+ Trace.beginSection("$TAG#onStartTransition")
listeners.forEach { it.onTransitionStarted() }
Trace.endSection()
@@ -195,8 +228,39 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
listeners.remove(listener)
}
+ private fun startCannedCancelAnimation() {
+ cannedAnimator?.cancel()
+ cannedAnimator = null
+
+ // Temporary remove listener to cancel the spring animation without
+ // finishing the transition
+ springAnimation.removeEndListener(this)
+ springAnimation.cancel()
+ springAnimation.addEndListener(this)
+
+ cannedAnimator =
+ ObjectAnimator.ofFloat(this, AnimationProgressProperty, transitionProgress, 1f).apply {
+ addListener(CannedAnimationListener())
+ duration =
+ (CANNED_ANIMATION_DURATION_MS.toFloat() * (1f - transitionProgress)).toLong()
+ interpolator = emphasizedInterpolator
+ start()
+ }
+ }
+
+ private inner class CannedAnimationListener : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animator: Animator) {
+ Trace.beginAsyncSection("$TAG#cannedAnimatorRunning", 0)
+ }
+
+ override fun onAnimationEnd(animator: Animator) {
+ cancelTransition(1f, animate = false)
+ Trace.endAsyncSection("$TAG#cannedAnimatorRunning", 0)
+ }
+ }
+
private object AnimationProgressProperty :
- FloatPropertyCompat<PhysicsBasedUnfoldTransitionProgressProvider>("animation_progress") {
+ FloatProperty<PhysicsBasedUnfoldTransitionProgressProvider>("animation_progress") {
override fun setValue(
provider: PhysicsBasedUnfoldTransitionProgressProvider,
@@ -205,7 +269,7 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
provider.transitionProgress = value
}
- override fun getValue(provider: PhysicsBasedUnfoldTransitionProgressProvider): Float =
+ override fun get(provider: PhysicsBasedUnfoldTransitionProgressProvider): Float =
provider.transitionProgress
}
}
@@ -213,6 +277,8 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
private const val TAG = "PhysicsBasedUnfoldTransitionProgressProvider"
private const val DEBUG = true
+private const val USE_CANNED_ANIMATION = true
+private const val CANNED_ANIMATION_DURATION_MS = 1000
private const val SPRING_STIFFNESS = 600.0f
private const val MINIMAL_VISIBLE_CHANGE = 0.001f
private const val FINAL_HINGE_ANGLE_POSITION = 165f