drm_hwcomposer: composite down to a primary plane after a timeout

DrmDisplayCompositor::SquashAll is triggered after a constant timeout in
DrmCompositorWorker::Routine. It will not be triggered more than one time
between genuine hwc_set calls. SquashAll has no effect if there are protected
layers, only one layer, or any errors. On success, SquashAll produces a new
DrmDisplayComposition that owns the layers in the planes of the active
composition and makes that the new active composition. SquashAll has no effect
on SquashState.

Change-Id: I975edb21847dcf2d93245f92a6e53a4e366c6a3b
diff --git a/drmcompositorworker.cpp b/drmcompositorworker.cpp
index c8eae5f..9804322 100644
--- a/drmcompositorworker.cpp
+++ b/drmcompositorworker.cpp
@@ -27,6 +27,8 @@
 
 namespace android {
 
+static const int64_t kSquashWait = 500000000LL;
+
 DrmCompositorWorker::DrmCompositorWorker(DrmDisplayCompositor *compositor)
     : Worker("drm-compositor", HAL_PRIORITY_URGENT_DISPLAY),
       compositor_(compositor) {
@@ -48,7 +50,11 @@
       return;
     }
 
-    int wait_ret = WaitForSignalOrExitLocked();
+    // Only use a timeout if we didn't do a SquashAll last time. This will
+    // prevent wait_ret == -ETIMEDOUT which would trigger a SquashAll and be a
+    // pointless drain on resources.
+    int wait_ret = did_squash_all_ ? WaitForSignalOrExitLocked()
+                                   : WaitForSignalOrExitLocked(kSquashWait);
 
     ret = Unlock();
     if (ret) {
@@ -56,16 +62,26 @@
       return;
     }
 
-    if (wait_ret == -EINTR) {
-      return;
-    } else if (wait_ret) {
-      ALOGE("Failed to wait for signal, %d", wait_ret);
-      return;
+    switch (wait_ret) {
+      case 0:
+        break;
+      case -EINTR:
+        return;
+      case -ETIMEDOUT:
+        ret = compositor_->SquashAll();
+        if (ret)
+          ALOGE("Failed to squash all %d", ret);
+        did_squash_all_ = true;
+        return;
+      default:
+        ALOGE("Failed to wait for signal, %d", wait_ret);
+        return;
     }
   }
 
   ret = compositor_->Composite();
   if (ret)
     ALOGE("Failed to composite! %d", ret);
+  did_squash_all_ = false;
 }
 }