Merge "Fix performance regressions" into tm-qpr-dev am: e8b7907312

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21422787

Change-Id: Ie1cdcb55ac0dbed9f17c3d682d84fbb57b245161
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Fabian Kozynski
2023-02-16 16:51:31 +00:00
committed by Automerger Merge Worker
2 changed files with 62 additions and 83 deletions

View File

@@ -17,6 +17,7 @@
package com.android.systemui.shade package com.android.systemui.shade
import android.animation.Animator import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.annotation.IdRes import android.annotation.IdRes
import android.app.StatusBarManager import android.app.StatusBarManager
import android.content.res.Configuration import android.content.res.Configuration
@@ -145,6 +146,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
updateListeners() updateListeners()
} }
private var customizing = false
set(value) {
if (field != value) {
field = value
updateVisibility()
}
}
/** /**
* Whether the QQS/QS part of the shade is visible. This is particularly important in * Whether the QQS/QS part of the shade is visible. This is particularly important in
* Lockscreen, as the shade is visible but QS is not. * Lockscreen, as the shade is visible but QS is not.
@@ -176,14 +185,9 @@ class LargeScreenShadeHeaderController @Inject constructor(
*/ */
var shadeExpandedFraction = -1f var shadeExpandedFraction = -1f
set(value) { set(value) {
if (field != value) { if (qsVisible && field != value) {
val oldAlpha = header.alpha
header.alpha = ShadeInterpolation.getContentAlpha(value) header.alpha = ShadeInterpolation.getContentAlpha(value)
field = value field = value
if ((oldAlpha == 0f && header.alpha > 0f) ||
(oldAlpha > 0f && header.alpha == 0f)) {
updateVisibility()
}
} }
} }
@@ -318,6 +322,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
dumpManager.registerDumpable(this) dumpManager.registerDumpable(this)
configurationController.addCallback(configurationControllerListener) configurationController.addCallback(configurationControllerListener)
demoModeController.addCallback(demoModeReceiver) demoModeController.addCallback(demoModeReceiver)
statusBarIconController.addIconGroup(iconManager)
} }
override fun onViewDetached() { override fun onViewDetached() {
@@ -325,6 +330,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
dumpManager.unregisterDumpable(this::class.java.simpleName) dumpManager.unregisterDumpable(this::class.java.simpleName)
configurationController.removeCallback(configurationControllerListener) configurationController.removeCallback(configurationControllerListener)
demoModeController.removeCallback(demoModeReceiver) demoModeController.removeCallback(demoModeReceiver)
statusBarIconController.removeIconGroup(iconManager)
} }
fun disable(state1: Int, state2: Int, animate: Boolean) { fun disable(state1: Int, state2: Int, animate: Boolean) {
@@ -339,31 +345,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
.setDuration(duration) .setDuration(duration)
.alpha(if (show) 0f else 1f) .alpha(if (show) 0f else 1f)
.setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN) .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
.setUpdateListener { .setListener(CustomizerAnimationListener(show))
updateVisibility()
}
.setListener(endAnimationListener)
.start() .start()
} }
private val endAnimationListener = object : Animator.AnimatorListener {
override fun onAnimationCancel(animation: Animator?) {
clearListeners()
}
override fun onAnimationEnd(animation: Animator?) {
clearListeners()
}
override fun onAnimationRepeat(animation: Animator?) {}
override fun onAnimationStart(animation: Animator?) {}
private fun clearListeners() {
header.animate().setListener(null).setUpdateListener(null)
}
}
private fun loadConstraints() { private fun loadConstraints() {
if (header is MotionLayout) { if (header is MotionLayout) {
// Use resources.getXml instead of passing the resource id due to bug b/205018300 // Use resources.getXml instead of passing the resource id due to bug b/205018300
@@ -453,7 +438,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
private fun updateVisibility() { private fun updateVisibility() {
val visibility = if (!largeScreenActive && !combinedHeaders || qsDisabled) { val visibility = if (!largeScreenActive && !combinedHeaders || qsDisabled) {
View.GONE View.GONE
} else if (qsVisible && header.alpha > 0f) { } else if (qsVisible && !customizing) {
View.VISIBLE View.VISIBLE
} else { } else {
View.INVISIBLE View.INVISIBLE
@@ -502,10 +487,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
if (visible) { if (visible) {
updateSingleCarrier(qsCarrierGroupController.isSingleCarrier) updateSingleCarrier(qsCarrierGroupController.isSingleCarrier)
qsCarrierGroupController.setOnSingleCarrierChangedListener { updateSingleCarrier(it) } qsCarrierGroupController.setOnSingleCarrierChangedListener { updateSingleCarrier(it) }
statusBarIconController.addIconGroup(iconManager)
} else { } else {
qsCarrierGroupController.setOnSingleCarrierChangedListener(null) qsCarrierGroupController.setOnSingleCarrierChangedListener(null)
statusBarIconController.removeIconGroup(iconManager)
} }
} }
@@ -578,4 +561,23 @@ class LargeScreenShadeHeaderController @Inject constructor(
@VisibleForTesting @VisibleForTesting
internal fun simulateViewDetached() = this.onViewDetached() internal fun simulateViewDetached() = this.onViewDetached()
inner class CustomizerAnimationListener(
private val enteringCustomizing: Boolean,
) : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
header.animate().setListener(null)
if (enteringCustomizing) {
customizing = true
}
}
override fun onAnimationStart(animation: Animator?) {
super.onAnimationStart(animation)
if (!enteringCustomizing) {
customizing = false
}
}
}
} }

View File

@@ -1,7 +1,6 @@
package com.android.systemui.shade package com.android.systemui.shade
import android.animation.Animator import android.animation.Animator
import android.animation.ValueAnimator
import android.app.StatusBarManager import android.app.StatusBarManager
import android.content.Context import android.content.Context
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
@@ -44,6 +43,7 @@ import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
@@ -158,9 +158,19 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
fun updateListeners_registersWhenVisible() { fun updateListeners_registersWhenVisible() {
makeShadeVisible() makeShadeVisible()
verify(qsCarrierGroupController).setListening(true) verify(qsCarrierGroupController).setListening(true)
}
@Test
fun statusIconsAddedWhenAttached() {
verify(statusBarIconController).addIconGroup(any()) verify(statusBarIconController).addIconGroup(any())
} }
@Test
fun statusIconsRemovedWhenDettached() {
mLargeScreenShadeHeaderController.simulateViewDetached()
verify(statusBarIconController).removeIconGroup(any())
}
@Test @Test
fun shadeExpandedFraction_updatesAlpha() { fun shadeExpandedFraction_updatesAlpha() {
makeShadeVisible() makeShadeVisible()
@@ -168,16 +178,6 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f)) verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
} }
@Test
fun alphaChangesUpdateVisibility() {
makeShadeVisible()
mLargeScreenShadeHeaderController.shadeExpandedFraction = 0f
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
mLargeScreenShadeHeaderController.shadeExpandedFraction = 1f
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
}
@Test @Test
fun singleCarrier_enablesCarrierIconsInStatusIcons() { fun singleCarrier_enablesCarrierIconsInStatusIcons() {
whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true) whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
@@ -263,40 +263,32 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
} }
@Test @Test
fun testShadeExpanded_true_alpha_zero_invisible() { fun customizerAnimatorChangesViewVisibility() {
view.alpha = 0f makeShadeVisible()
mLargeScreenShadeHeaderController.largeScreenActive = true
mLargeScreenShadeHeaderController.qsVisible = true
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
}
@Test
fun animatorCallsUpdateVisibilityOnUpdate() {
val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
val duration = 1000L
whenever(view.animate()).thenReturn(animator) whenever(view.animate()).thenReturn(animator)
val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, 0L) mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration)
verify(animator).setListener(capture(listenerCaptor))
val updateCaptor = argumentCaptor<ValueAnimator.AnimatorUpdateListener>() // Start and end the animation
verify(animator).setUpdateListener(capture(updateCaptor)) listenerCaptor.value.onAnimationStart(mock())
listenerCaptor.value.onAnimationEnd(mock())
mLargeScreenShadeHeaderController.largeScreenActive = true
mLargeScreenShadeHeaderController.qsVisible = true
view.alpha = 1f
updateCaptor.value.onAnimationUpdate(mock())
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
view.alpha = 0f
updateCaptor.value.onAnimationUpdate(mock())
assertThat(viewVisibility).isEqualTo(View.INVISIBLE) assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
reset(animator)
mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration)
verify(animator).setListener(capture(listenerCaptor))
// Start and end the animation
listenerCaptor.value.onAnimationStart(mock())
listenerCaptor.value.onAnimationEnd(mock())
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
} }
@Test @Test
fun animatorListenersClearedAtEnd() { fun animatorListenerClearedAtEnd() {
val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
whenever(view.animate()).thenReturn(animator) whenever(view.animate()).thenReturn(animator)
@@ -306,21 +298,6 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
listenerCaptor.value.onAnimationEnd(mock()) listenerCaptor.value.onAnimationEnd(mock())
verify(animator).setListener(null) verify(animator).setListener(null)
verify(animator).setUpdateListener(null)
}
@Test
fun animatorListenersClearedOnCancel() {
val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
whenever(view.animate()).thenReturn(animator)
mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, 0L)
val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
verify(animator).setListener(capture(listenerCaptor))
listenerCaptor.value.onAnimationCancel(mock())
verify(animator).setListener(null)
verify(animator).setUpdateListener(null)
} }
@Test @Test