[AChoreographer] Resolves a deadlock

This deadlock could occur when posting a delayed frame callback while a
pending refresh rate callback had not yet been processed by the looper
thread. Resolve the deadlock by releasing the lock in
Choreographer::scheduleCallbacks once the earliest dueTime is retrieved.

Bug: 150731776
Test: ChoreographerNativeTest
Change-Id: I9e1ace12beb4bbc75af0671ddf1b1653d04c9df4
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 0f7e2fb..0ff33ac 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -185,9 +185,18 @@
 }
 
 void Choreographer::scheduleCallbacks() {
-    AutoMutex _{mLock};
-    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    if (mFrameCallbacks.top().dueTime <= now) {
+    const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    nsecs_t dueTime;
+    {
+        AutoMutex _{mLock};
+        // If there are no pending callbacks then don't schedule a vsync
+        if (mFrameCallbacks.empty()) {
+            return;
+        }
+        dueTime = mFrameCallbacks.top().dueTime;
+    }
+
+    if (dueTime <= now) {
         ALOGV("choreographer %p ~ scheduling vsync", this);
         scheduleVsync();
         return;