drm_hwcomposer: On error, free active composition

If we drop a frame while compositing, free the active composition.

Assume a frame pipeline of A->B->A. If we drop frame B, it will become
the active composition, which means the fences for A will not be released,
causing us to block A on A --> DEADLOCK.

BUG=b/29122961
TEST=Tested on smaug, no longer hangs

Change-Id: I98817bb361f1d0669395ddac5d96cf4f19d4b26a
Signed-off-by: Sean Paul <seanpaul@chromium.org>
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 0b2506f..279d5a6 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -864,6 +864,23 @@
   return std::make_tuple(ret, id);
 }
 
+void DrmDisplayCompositor::ClearDisplay() {
+  AutoLock lock(&lock_, "compositor");
+  int ret = lock.Lock();
+  if (ret)
+    return;
+
+  if (!active_composition_)
+    return;
+
+  if (DisablePlanes(active_composition_.get()))
+    return;
+
+  active_composition_->SignalCompositionDone();
+
+  active_composition_.reset(NULL);
+}
+
 void DrmDisplayCompositor::ApplyFrame(
     std::unique_ptr<DrmDisplayComposition> composition, int status) {
   int ret = status;
@@ -873,11 +890,10 @@
 
   if (ret) {
     ALOGE("Composite failed for display %d", display_);
-
     // Disable the hw used by the last active composition. This allows us to
     // signal the release fences from that composition to avoid hanging.
-    if (DisablePlanes(active_composition_.get()))
-      return;
+    ClearDisplay();
+    return;
   }
   ++dump_frames_composited_;
 
@@ -958,6 +974,10 @@
           composition = std::move(squashed);
         } else {
           ALOGE("Failed to squash frame for display %d", display_);
+          // Disable the hw used by the last active composition. This allows us
+          // to signal the release fences from that composition to avoid
+          // hanging.
+          ClearDisplay();
           return ret;
         }
       }