Attempting to fix the black flicker

Bug: 79231206
Test: Repro steps from bug

Merged-In: I4c2810c42a7a4358f64584da3ab0cdf1499e71b6
Change-Id: I4c2810c42a7a4358f64584da3ab0cdf1499e71b6
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2ddf55b..aed0620 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -46,6 +46,7 @@
 #include <algorithm>
 
 #include <cstdlib>
+#include <functional>
 
 #define TRIM_MEMORY_COMPLETE 80
 #define TRIM_MEMORY_UI_HIDDEN 20
@@ -383,6 +384,12 @@
         info.out.canDrawThisFrame = true;
     }
 
+    // TODO: Do we need to abort out if the backdrop is added but not ready? Should that even
+    // be an allowable combination?
+    if (mRenderNodes.size() > 2 && !mRenderNodes[1]->isRenderable()) {
+        info.out.canDrawThisFrame = false;
+    }
+
     if (!info.out.canDrawThisFrame) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
     }
@@ -449,6 +456,8 @@
                                       mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
                                       mRenderNodes, &(profiler()));
 
+    int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
+
     waitOnFences();
 
     bool requireSwap = false;
@@ -509,6 +518,13 @@
     }
 #endif
 
+    if (didSwap) {
+        for (auto& func : mFrameCompleteCallbacks) {
+            std::invoke(func, frameCompleteNr);
+        }
+        mFrameCompleteCallbacks.clear();
+    }
+
     mJankTracker.finishFrame(*mCurrentFrameInfo);
     if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
         mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e52b644..1c4e02d 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -190,6 +190,10 @@
 
     IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
 
+    void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
+        mFrameCompleteCallbacks.push_back(std::move(func));
+    }
+
 private:
     CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                   IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
@@ -267,6 +271,8 @@
     std::vector<sp<FuncTask>> mFrameFences;
     sp<TaskProcessor<bool>> mFrameWorkProcessor;
     std::unique_ptr<IRenderPipeline> mRenderPipeline;
+
+    std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 60df514..51eeab7 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -90,6 +90,11 @@
         TreeInfo info(TreeInfo::MODE_FULL, *mContext);
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
+
+        if (mFrameCompleteCallback) {
+            mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
+            mFrameCompleteCallback = nullptr;
+        }
     }
 
     // Grab a copy of everything we need
@@ -152,6 +157,9 @@
             mSyncResult |= SyncResult::UIRedrawRequired;
         }
     }
+    if (!info.out.canDrawThisFrame) {
+        mSyncResult |= SyncResult::FrameDropped;
+    }
     // If prepareTextures is false, we ran out of texture cache space
     return info.prepareTextures;
 }
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d8c43e0..2c46762f 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -46,6 +46,7 @@
     UIRedrawRequired = 1 << 0,
     LostSurfaceRewardIfFound = 1 << 1,
     ContextIsStopped = 1 << 2,
+    FrameDropped = 1 << 3,
 };
 }
 
@@ -78,6 +79,10 @@
         mFrameCallback = std::move(callback);
     }
 
+    void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+        mFrameCompleteCallback = std::move(callback);
+    }
+
 private:
     void postAndWait();
     bool syncFrameState(TreeInfo& info);
@@ -102,6 +107,7 @@
     int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 
     std::function<void(int64_t)> mFrameCallback;
+    std::function<void(int64_t)> mFrameCompleteCallback;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c6a9b55f..59048be 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -274,6 +274,10 @@
     mDrawFrameTask.setFrameCallback(std::move(callback));
 }
 
+void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+    mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
+}
+
 void RenderProxy::serializeDisplayListTree() {
     mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); });
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 3425c5c..ad534f0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -116,6 +116,7 @@
     ANDROID_API void drawRenderNode(RenderNode* node);
     ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
     ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback);
+    ANDROID_API void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
 
     ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
     ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);