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()
     }
 }