Merge "graphics: really reset HWC2 on SF crashes"
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index 72ba8f8..0114430 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -230,30 +230,69 @@
 
 ComposerClient::~ComposerClient()
 {
-    ALOGD("client destroyed");
+    // We want to call hwc2_close here (and move hwc2_open to the
+    // constructor), with the assumption that hwc2_close would
+    //
+    //  - clean up all resources owned by the client
+    //  - make sure all displays are blank (since there is no layer)
+    //
+    // But since SF used to crash at this point, different hwcomposer2
+    // implementations behave differently on hwc2_close.  Our only portable
+    // choice really is to abort().  But that is not an option anymore
+    // because we might also have VTS or VR as clients that can come and go.
+    //
+    // Below we manually clean all resources (layers and virtual
+    // displays), and perform a presentDisplay afterwards.
+    ALOGW("destroying composer client");
 
     mHal.enableCallback(false);
-    mHal.removeClient();
 
-    // no need to grab the mutex as any in-flight hwbinder call should keep
-    // the client alive
+    // no need to grab the mutex as any in-flight hwbinder call would have
+    // kept the client alive
     for (const auto& dpy : mDisplayData) {
-        if (!dpy.second.Layers.empty()) {
-            ALOGW("client destroyed with valid layers");
-        }
+        ALOGW("destroying client resources for display %" PRIu64, dpy.first);
+
         for (const auto& ly : dpy.second.Layers) {
             mHal.destroyLayer(dpy.first, ly.first);
         }
 
         if (dpy.second.IsVirtual) {
-            ALOGW("client destroyed with valid virtual display");
             mHal.destroyVirtualDisplay(dpy.first);
+        } else {
+            ALOGW("performing a final presentDisplay");
+
+            std::vector<Layer> changedLayers;
+            std::vector<IComposerClient::Composition> compositionTypes;
+            uint32_t displayRequestMask = 0;
+            std::vector<Layer> requestedLayers;
+            std::vector<uint32_t> requestMasks;
+            mHal.validateDisplay(dpy.first, &changedLayers, &compositionTypes,
+                    &displayRequestMask, &requestedLayers, &requestMasks);
+
+            mHal.acceptDisplayChanges(dpy.first);
+
+            int32_t presentFence = -1;
+            std::vector<Layer> releasedLayers;
+            std::vector<int32_t> releaseFences;
+            mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences);
+            if (presentFence >= 0) {
+                close(presentFence);
+            }
+            for (auto fence : releaseFences) {
+                if (fence >= 0) {
+                    close(fence);
+                }
+            }
         }
     }
 
     mDisplayData.clear();
 
     sHandleImporter.cleanup();
+
+    mHal.removeClient();
+
+    ALOGW("removed composer client");
 }
 
 void ComposerClient::initialize()