Run the ondrawn Keyguard callback in the bg thread
This should give some unfold latency improvements, as the screen is on only when the pending tasks registered in ScreenOnCoordinator are completed.
If there are some long running computations in the main thread, calling onDrawn.run() will result in delays.
Flag: ACONFIG enable_background_keyguard_ondrawn_callback DISABLED
Bug: 295873557
Test: ScreenOnCoordinatorTest
Change-Id: Ie0202eb96d7b155f0f3be90dc35a3b0ae9b8e8e3
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 41d12dc..b1b7902 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -145,6 +145,16 @@
}
flag {
+ name: "enable_background_keyguard_ondrawn_callback"
+ namespace: "systemui"
+ description: "Calls the onDrawn keyguard in the background, without being blocked by main"
+ "thread work. This results in the screen to turn on earlier when the main thread is stuck. "
+ "Note that, even after this callback is called, we're waiting for all windows to finish "
+ " drawing."
+ bug: "295873557"
+}
+
+flag {
name: "qs_new_pipeline"
namespace: "systemui"
description: "Use the new pipeline for Quick Settings. Should have no behavior changes."
diff --git a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
index 603471b..7a560e8 100644
--- a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
@@ -19,6 +19,7 @@
import android.annotation.BinderThread
import android.os.Handler
import android.os.Trace
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.unfold.SysUIUnfoldComponent
@@ -59,8 +60,11 @@
foldAodAnimationController?.onScreenTurningOn(pendingTasks.registerTask("fold-to-aod"))
pendingTasks.onTasksComplete {
- mainHandler.post {
+ if (Flags.enableBackgroundKeyguardOndrawnCallback()) {
+ // called by whatever thread completes the last task registered.
onDrawn.run()
+ } else {
+ mainHandler.post { onDrawn.run() }
}
}
Trace.endSection()
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
index 9fe32f1..b45c894 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
@@ -16,16 +16,21 @@
package com.android.keyguard.mediator
-import android.os.Handler
import android.os.Looper
+import android.platform.test.flag.junit.SetFlagsRule
+import android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.unfold.FoldAodAnimationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation
import com.android.systemui.util.mockito.capture
+import com.android.systemui.utils.os.FakeHandler
+import com.android.systemui.utils.os.FakeHandler.Mode.QUEUEING
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
@@ -52,10 +57,13 @@
@Captor
private lateinit var readyCaptor: ArgumentCaptor<Runnable>
- private val testHandler = Handler(Looper.getMainLooper())
+ private val testHandler = FakeHandler(Looper.getMainLooper()).apply { setMode(QUEUEING) }
private lateinit var screenOnCoordinator: ScreenOnCoordinator
+ @get:Rule
+ val setFlagsRule = SetFlagsRule(DEVICE_DEFAULT)
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -77,7 +85,7 @@
onUnfoldOverlayReady()
onFoldAodReady()
- waitHandlerIdle(testHandler)
+ waitHandlerIdle()
// Should be called when both unfold overlay and keyguard drawn ready
verify(runnable).run()
@@ -90,7 +98,7 @@
onUnfoldOverlayReady()
onFoldAodReady()
- waitHandlerIdle(testHandler)
+ waitHandlerIdle()
// Should be called when both unfold overlay and keyguard drawn ready
verify(runnable).run()
@@ -104,7 +112,8 @@
onUnfoldOverlayReady()
onFoldAodReady()
- waitHandlerIdle(testHandler)
+ waitHandlerIdle()
+
// Should not be called because this screen turning on call is not valid anymore
verify(runnable, never()).run()
@@ -112,13 +121,43 @@
@Test
fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_callsDrawnCallback() {
+ setFlagsRule.disableFlags(Flags.FLAG_ENABLE_BACKGROUND_KEYGUARD_ONDRAWN_CALLBACK)
// Recreate with empty unfoldComponent
screenOnCoordinator = ScreenOnCoordinator(
Optional.empty(),
testHandler
)
screenOnCoordinator.onScreenTurningOn(runnable)
- waitHandlerIdle(testHandler)
+ waitHandlerIdle()
+
+ // Should be called when only keyguard drawn
+ verify(runnable).run()
+ }
+ @Test
+ fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_usesMainHandler() {
+ setFlagsRule.disableFlags(Flags.FLAG_ENABLE_BACKGROUND_KEYGUARD_ONDRAWN_CALLBACK)
+ // Recreate with empty unfoldComponent
+ screenOnCoordinator = ScreenOnCoordinator(
+ Optional.empty(),
+ testHandler
+ )
+ screenOnCoordinator.onScreenTurningOn(runnable)
+
+ // Never called as the main handler didn't schedule it yet.
+ verify(runnable, never()).run()
+ }
+
+ @Test
+ fun unfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_bgCallback_callsDrawnCallback() {
+ setFlagsRule.enableFlags(Flags.FLAG_ENABLE_BACKGROUND_KEYGUARD_ONDRAWN_CALLBACK)
+ // Recreate with empty unfoldComponent
+ screenOnCoordinator = ScreenOnCoordinator(
+ Optional.empty(),
+ testHandler
+ )
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ // No need to wait for the handler to be idle, as it shouldn't be used
+ // waitHandlerIdle()
// Should be called when only keyguard drawn
verify(runnable).run()
@@ -134,7 +173,7 @@
readyCaptor.value.run()
}
- private fun waitHandlerIdle(handler: Handler) {
- handler.runWithScissors({}, /* timeout= */ 0)
+ private fun waitHandlerIdle() {
+ testHandler.dispatchQueuedMessages()
}
}