diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index ea38db304e6d7..0d4ad382222fd 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -42,6 +42,8 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF; +import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; @@ -177,6 +179,8 @@ public class InteractionJankMonitor { public static final int CUJ_USER_SWITCH = 37; public static final int CUJ_SPLASHSCREEN_AVD = 38; public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = 39; + public static final int CUJ_SCREEN_OFF = 40; + public static final int CUJ_SCREEN_OFF_SHOW_AOD = 41; private static final int NO_STATSD_LOGGING = -1; @@ -225,6 +229,8 @@ public class InteractionJankMonitor { UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD, UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF, + UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD, }; private static volatile InteractionJankMonitor sInstance; @@ -285,6 +291,8 @@ public class InteractionJankMonitor { CUJ_USER_SWITCH, CUJ_SPLASHSCREEN_AVD, CUJ_SPLASHSCREEN_EXIT_ANIM, + CUJ_SCREEN_OFF, + CUJ_SCREEN_OFF_SHOW_AOD, }) @Retention(RetentionPolicy.SOURCE) public @interface CujType { @@ -422,6 +430,16 @@ public class InteractionJankMonitor { } } + /** + * @param cujType cuj type + * @return true if the cuj is under instrumenting, false otherwise. + */ + public boolean isInstrumenting(@CujType int cujType) { + synchronized (mLock) { + return mRunningTrackers.contains(cujType); + } + } + /** * Begins a trace session. * @@ -690,6 +708,10 @@ public class InteractionJankMonitor { return "SPLASHSCREEN_AVD"; case CUJ_SPLASHSCREEN_EXIT_ANIM: return "SPLASHSCREEN_EXIT_ANIM"; + case CUJ_SCREEN_OFF: + return "SCREEN_OFF"; + case CUJ_SCREEN_OFF_SHOW_AOD: + return "SCREEN_OFF_SHOW_AOD"; } return "UNKNOWN"; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt index 03d8e7e03c0fc..c8115e2c197a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt @@ -92,6 +92,8 @@ class LinearLightRevealEffect(private val isVertical: Boolean) : LightRevealEffe override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) { val interpolatedAmount = INTERPOLATOR.getInterpolation(amount) + scrim.interpolatedRevealAmount = interpolatedAmount + scrim.startColorAlpha = getPercentPastThreshold(1 - interpolatedAmount, threshold = 1 - START_COLOR_REVEAL_PERCENTAGE) @@ -152,6 +154,7 @@ class CircleReveal( // non-interpolated amount val fadeAmount = getPercentPastThreshold(amount, 0.5f) val radius = startRadius + ((endRadius - startRadius) * amount) + scrim.interpolatedRevealAmount = amount scrim.revealGradientEndColorAlpha = 1f - fadeAmount scrim.setRevealGradientBounds( centerX - radius /* left */, @@ -182,6 +185,7 @@ class PowerButtonReveal( with(scrim) { revealGradientEndColorAlpha = 1f - fadeAmount + interpolatedRevealAmount = interpolatedAmount setRevealGradientBounds( width * (1f + OFF_SCREEN_START_AMOUNT) - width * WIDTH_INCREASE_MULTIPLIER * interpolatedAmount, @@ -284,6 +288,14 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, } } + var interpolatedRevealAmount: Float = 1f + + val isScrimAlmostOccludes: Boolean + get() { + // if the interpolatedRevealAmount less than 0.1, over 90% of the screen is black. + return interpolatedRevealAmount < 0.1f + } + private fun updateScrimOpaque() { isScrimOpaque = revealAmount == 0.0f && alpha == 1.0f && visibility == VISIBLE } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index 92c76dc196b98..0ba713464b806 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -9,6 +9,9 @@ import android.os.Handler import android.provider.Settings import android.view.Surface import android.view.View +import com.android.internal.jank.InteractionJankMonitor +import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF +import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.KeyguardViewMediator @@ -50,7 +53,8 @@ class UnlockedScreenOffAnimationController @Inject constructor( private val keyguardViewMediatorLazy: dagger.Lazy, private val keyguardStateController: KeyguardStateController, private val dozeParameters: dagger.Lazy, - private val globalSettings: GlobalSettings + private val globalSettings: GlobalSettings, + private val interactionJankMonitor: InteractionJankMonitor ) : WakefulnessLifecycle.Observer, ScreenOffAnimation { private val handler = Handler() @@ -78,17 +82,28 @@ class UnlockedScreenOffAnimationController @Inject constructor( sendUnlockedScreenOffProgressUpdate( 1f - (it.animatedFraction as Float), 1f - (it.animatedValue as Float)) + if (lightRevealScrim.isScrimAlmostOccludes && + interactionJankMonitor.isInstrumenting(CUJ_SCREEN_OFF)) { + // ends the instrument when the scrim almost occludes the screen. + // because the following janky frames might not be perceptible. + interactionJankMonitor.end(CUJ_SCREEN_OFF) + } } addListener(object : AnimatorListenerAdapter() { override fun onAnimationCancel(animation: Animator?) { lightRevealScrim.revealAmount = 1f lightRevealAnimationPlaying = false sendUnlockedScreenOffProgressUpdate(0f, 0f) + interactionJankMonitor.cancel(CUJ_SCREEN_OFF) } override fun onAnimationEnd(animation: Animator?) { lightRevealAnimationPlaying = false } + + override fun onAnimationStart(animation: Animator?) { + interactionJankMonitor.begin(statusBar.notificationShadeWindowView, CUJ_SCREEN_OFF) + } }) } @@ -163,6 +178,16 @@ class UnlockedScreenOffAnimationController @Inject constructor( decidedToAnimateGoingToSleep = null // We need to unset the listener. These are persistent for future animators keyguardView.animate().setListener(null) + interactionJankMonitor.end(CUJ_SCREEN_OFF_SHOW_AOD) + } + + override fun onAnimationCancel(animation: Animator?) { + interactionJankMonitor.cancel(CUJ_SCREEN_OFF_SHOW_AOD) + } + + override fun onAnimationStart(animation: Animator?) { + interactionJankMonitor.begin( + statusBar.notificationShadeWindowView, CUJ_SCREEN_OFF_SHOW_AOD) } }) .start() @@ -244,10 +269,10 @@ class UnlockedScreenOffAnimationController @Inject constructor( // already expanded and showing notifications/QS, the animation looks really messy. For now, // disable it if the notification panel is not fully collapsed. if ((!this::statusBar.isInitialized || - !statusBar.notificationPanelViewController.isFullyCollapsed) + !statusBar.notificationPanelViewController.isFullyCollapsed) && // Status bar might be expanded because we have started // playing the animation already - && !isAnimationPlaying() + !isAnimationPlaying() ) { return false } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt index a8a33dabf1aac..24a56bc76faec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt @@ -21,6 +21,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.View import androidx.test.filters.SmallTest +import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle @@ -59,6 +60,8 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var statusBarStateController: StatusBarStateControllerImpl + @Mock + private lateinit var interactionJankMonitor: InteractionJankMonitor @Before fun setUp() { @@ -71,7 +74,8 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { dagger.Lazy { keyguardViewMediator }, keyguardStateController, dagger.Lazy { dozeParameters }, - globalSettings + globalSettings, + interactionJankMonitor ) controller.initialize(statusbar, lightRevealScrim) }