Merge "getProcessFreezeInfo reads more info from kernel" into sc-qpr1-dev
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index d860f30..94e1ae1 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -630,7 +630,10 @@
 
 class BBQSurface : public Surface {
 private:
+    std::mutex mMutex;
     sp<BLASTBufferQueue> mBbq;
+    bool mDestroyed = false;
+
 public:
     BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
                const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
@@ -650,6 +653,10 @@
 
     status_t setFrameRate(float frameRate, int8_t compatibility,
                           int8_t changeFrameRateStrategy) override {
+        std::unique_lock _lock{mMutex};
+        if (mDestroyed) {
+            return DEAD_OBJECT;
+        }
         if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
                                "BBQSurface::setFrameRate")) {
             return BAD_VALUE;
@@ -658,8 +665,20 @@
     }
 
     status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override {
+        std::unique_lock _lock{mMutex};
+        if (mDestroyed) {
+            return DEAD_OBJECT;
+        }
         return mBbq->setFrameTimelineInfo(frameTimelineInfo);
     }
+
+    void destroy() override {
+        Surface::destroy();
+
+        std::unique_lock _lock{mMutex};
+        mDestroyed = true;
+        mBbq = nullptr;
+    }
 };
 
 // TODO: Can we coalesce this with frame updates? Need to confirm
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 2edb4e4..353a91d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -2622,4 +2622,14 @@
     return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
 }
 
+sp<IBinder> Surface::getSurfaceControlHandle() const {
+    Mutex::Autolock lock(mMutex);
+    return mSurfaceControlHandle;
+}
+
+void Surface::destroy() {
+    Mutex::Autolock lock(mMutex);
+    mSurfaceControlHandle = nullptr;
+}
+
 }; // namespace android
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 7e4143b..e540351 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -99,7 +99,7 @@
      */
     sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
 
-    sp<IBinder> getSurfaceControlHandle() const { return mSurfaceControlHandle; }
+    sp<IBinder> getSurfaceControlHandle() const;
 
     /* convenience function to check that the given surface is non NULL as
      * well as its IGraphicBufferProducer */
@@ -333,6 +333,7 @@
     virtual int connect(
             int api, bool reportBufferRemoval,
             const sp<SurfaceListener>& sListener);
+    virtual void destroy();
 
     // When client connects to Surface with reportBufferRemoval set to true, any buffers removed
     // from this Surface will be collected and returned here. Once this method returns, these
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 3c59f11..94023e6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -424,14 +424,28 @@
     return fenceFd;
 }
 
-bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
+void SkiaGLRenderEngine::waitFence(base::borrowed_fd fenceFd) {
+    if (fenceFd.get() >= 0 && !waitGpuFence(fenceFd)) {
+        ATRACE_NAME("SkiaGLRenderEngine::waitFence");
+        sync_wait(fenceFd.get(), -1);
+    }
+}
+
+bool SkiaGLRenderEngine::waitGpuFence(base::borrowed_fd fenceFd) {
     if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
         !gl::GLExtensions::getInstance().hasWaitSync()) {
         return false;
     }
 
+    // Duplicate the fence for passing to eglCreateSyncKHR.
+    base::unique_fd fenceDup(dup(fenceFd.get()));
+    if (fenceDup.get() < 0) {
+        ALOGE("failed to create duplicate fence fd: %d", fenceDup.get());
+        return false;
+    }
+
     // release the fd and transfer the ownership to EGLSync
-    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
+    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceDup.release(), EGL_NONE};
     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
     if (sync == EGL_NO_SYNC_KHR) {
         ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
@@ -726,14 +740,6 @@
         return NO_ERROR;
     }
 
-    if (bufferFence.get() >= 0) {
-        // Duplicate the fence for passing to waitFence.
-        base::unique_fd bufferFenceDup(dup(bufferFence.get()));
-        if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
-            ATRACE_NAME("Waiting before draw");
-            sync_wait(bufferFence.get(), -1);
-        }
-    }
     if (buffer == nullptr) {
         ALOGE("No output buffer provided. Aborting GPU composition.");
         return BAD_VALUE;
@@ -758,6 +764,9 @@
                                                                true, mTextureCleanupMgr);
     }
 
+    // wait on the buffer to be ready to use prior to using it
+    waitFence(bufferFence);
+
     const ui::Dataspace dstDataspace =
             mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
     sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext);
@@ -1014,6 +1023,12 @@
                                                       false, mTextureCleanupMgr);
             }
 
+            // if the layer's buffer has a fence, then we must must respect the fence prior to using
+            // the buffer.
+            if (layer->source.buffer.fence != nullptr) {
+                waitFence(layer->source.buffer.fence->get());
+            }
+
             // isOpaque means we need to ignore the alpha in the image,
             // replacing it with the alpha specified by the LayerSettings. See
             // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index a852bbc..238ad8f 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -99,7 +99,10 @@
     inline GrDirectContext* getActiveGrContext() const;
 
     base::unique_fd flush();
-    bool waitFence(base::unique_fd fenceFd);
+    // waitFence attempts to wait in the GPU, and if unable to waits on the CPU instead.
+    void waitFence(base::borrowed_fd fenceFd);
+    bool waitGpuFence(base::borrowed_fd fenceFd);
+
     void initCanvas(SkCanvas* canvas, const DisplaySettings& display);
     void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect,
                     const ShadowSettings& shadowSettings);