SF: Clean framebuffer cache on hotplug

This CL cleans the framebuffer cache when a hotplug event
for already connected display is processed. This way when we
destruct the DisplayDevice the framebuffers will be completely
deallocated, so they can later be reallocated.

Test: 1. unplug HDMI
      2. adb shell dumpsys SurfaceFlinger | grep FramebufferSurface
         verify only 3 framebuffers are allocated
      3. plug HDMI
      5. adb shell dumpsys SurfaceFlinger | grep FramebufferSurface
         verify only 3 framebuffers are allocated
Test: Using dev SurfaceFlinger backdoor (1036) which injects hotplug:
      adb shell service call SurfaceFlinger 1036 && \
        adb shell dumpsys SurfaceFlinger | grep FramebufferSurface
Bug: 160112047
Bug: 167670568
Change-Id: I96282bec439ebf413dcd5d57f6b884eccef19c5f
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 3090d19..42e74df 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -451,15 +451,10 @@
 GLESRenderEngine::~GLESRenderEngine() {
     // Destroy the image manager first.
     mImageManager = nullptr;
+    cleanFramebufferCache();
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     unbindFrameBuffer(mDrawingBuffer.get());
     mDrawingBuffer = nullptr;
-    while (!mFramebufferImageCache.empty()) {
-        EGLImageKHR expired = mFramebufferImageCache.front().second;
-        mFramebufferImageCache.pop_front();
-        eglDestroyImageKHR(mEGLDisplay, expired);
-        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
-    }
     eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
     mImageCache.clear();
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -965,6 +960,7 @@
     // Bind the texture to placeholder so that backing image data can be freed.
     GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
     glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
+
     // Release the cached fence here, so that we don't churn reallocations when
     // we could no-op repeated calls of this method instead.
     mLastDrawFence = nullptr;
@@ -972,6 +968,20 @@
     return true;
 }
 
+void GLESRenderEngine::cleanFramebufferCache() {
+    std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
+    // Bind the texture to placeholder so that backing image data can be freed.
+    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
+    glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
+
+    while (!mFramebufferImageCache.empty()) {
+        EGLImageKHR expired = mFramebufferImageCache.front().second;
+        mFramebufferImageCache.pop_front();
+        eglDestroyImageKHR(mEGLDisplay, expired);
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
+    }
+}
+
 void GLESRenderEngine::checkErrors() const {
     checkErrors(nullptr);
 }
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 2a98bd8..8f0df2c 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -135,6 +135,7 @@
     status_t bindFrameBuffer(Framebuffer* framebuffer);
     void unbindFrameBuffer(Framebuffer* framebuffer);
     void bindExternalTextureImage(uint32_t texName, const Image& image);
+    void cleanFramebufferCache() EXCLUDES(mFramebufferImageCacheMutex) override;
 
     // A data space is considered HDR data space if it has BT2020 color space
     // with PQ or HLG transfer function.