Add extra tests for renderengine

* Test buffer binding methods
* Test caching, and fix a bug caught by these tests.

Test: librenderengine_test
Change-Id: I50623d3a3f0b77f541044354c70db9fb536e66c3
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 48854e2..f651309 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -432,10 +432,15 @@
 }
 
 GLESRenderEngine::~GLESRenderEngine() {
-    for (const auto& image : mFramebufferImageCache) {
-        eglDestroyImageKHR(mEGLDisplay, image.second);
+    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);
     }
-    mFramebufferImageCache.clear();
+    mImageCache.clear();
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mEGLDisplay);
 }
@@ -634,6 +639,9 @@
 status_t GLESRenderEngine::bindExternalTextureBufferLocked(uint32_t texName,
                                                            sp<GraphicBuffer> buffer,
                                                            sp<Fence> bufferFence) {
+    if (buffer == nullptr) {
+        return BAD_VALUE;
+    }
     ATRACE_CALL();
     auto cachedImage = mImageCache.find(buffer->getId());
 
@@ -779,7 +787,7 @@
 EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
                                                              bool isProtected) {
     sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
-    uint32_t bufferId = graphicBuffer->getId();
+    uint64_t bufferId = graphicBuffer->getId();
     for (const auto& image : mFramebufferImageCache) {
         if (image.first == bufferId) {
             return image.second;
@@ -818,6 +826,11 @@
         sync_wait(bufferFence.get(), -1);
     }
 
+    if (buffer == nullptr) {
+        ALOGE("No output buffer provided. Aborting GPU composition.");
+        return BAD_VALUE;
+    }
+
     {
         std::lock_guard<std::mutex> lock(mRenderingMutex);
 
@@ -914,10 +927,12 @@
             }
         }
 
-        *drawFence = flush();
+        if (drawFence != nullptr) {
+            *drawFence = flush();
+        }
         // If flush failed or we don't support native fences, we need to force the
         // gl command stream to be executed.
-        if (drawFence->get() < 0) {
+        if (drawFence == nullptr || drawFence->get() < 0) {
             bool success = finish();
             if (!success) {
                 ALOGE("Failed to flush RenderEngine commands");
@@ -1343,6 +1358,20 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
+bool GLESRenderEngine::isImageCachedForTesting(uint64_t bufferId) {
+    std::lock_guard<std::mutex> lock(mRenderingMutex);
+    const auto& cachedImage = mImageCache.find(bufferId);
+    return cachedImage != mImageCache.end();
+}
+
+bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
+    std::lock_guard<std::mutex> lock(mRenderingMutex);
+    return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
+                       [=](std::pair<uint64_t, EGLImageKHR> image) {
+                           return image.first == bufferId;
+                       });
+}
+
 // FlushTracer implementation
 GLESRenderEngine::FlushTracer::FlushTracer(GLESRenderEngine* engine) : mEngine(engine) {
     mThread = std::thread(&GLESRenderEngine::FlushTracer::loop, this);