Fence on draws that are reported

Change-Id: Ib2ec16cbda40f40df1710bdc868869ea8301f17e
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index d6e1781..ad33b6f 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -1226,6 +1226,11 @@
     }
     private static native void nSetDisplayListData(long displayList, long newData);
 
+    @Override
+    void fence() {
+        // Everything is immediate, so this is a no-op
+    }
+
     private RenderNode buildDisplayList(View view, HardwareCanvas canvas) {
         if (mDrawDelta <= 0) {
             return view.mRenderNode;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 4f646e1..ae265aa 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -576,6 +576,11 @@
     abstract void setDisplayListData(long displayList, long newData);
 
     /**
+     * Blocks until all previously queued work has completed.
+     */
+    abstract void fence();
+
+    /**
      * Describes a series of frames that should be drawn on screen as a graph.
      * Each frame is composed of 1 or more elements.
      */
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 7b8a1ff..3d143d7 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -245,6 +245,11 @@
     }
 
     @Override
+    void fence() {
+        nFence(mNativeProxy);
+    }
+
+    @Override
     protected void finalize() throws Throwable {
         try {
             nDeleteProxy(mNativeProxy);
@@ -277,4 +282,6 @@
     private static native long nCreateTextureLayer(long nativeProxy);
     private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
     private static native void nDestroyLayer(long nativeProxy, long layer);
+
+    private static native void nFence(long nativeProxy);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a35c28e..94f0683 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2259,6 +2259,9 @@
 
         if (mReportNextDraw) {
             mReportNextDraw = false;
+            if (mAttachInfo.mHardwareRenderer != null) {
+                mAttachInfo.mHardwareRenderer.fence();
+            }
 
             if (LOCAL_LOGV) {
                 Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 98bec1b..32890cf 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -182,6 +182,12 @@
     proxy->destroyLayer(layer);
 }
 
+static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->fence();
+}
+
 #endif
 
 // ----------------------------------------------------------------------------
@@ -209,6 +215,7 @@
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
     { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
     { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
+    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
 #endif
 };
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index cd711b0..0b6be19 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -252,6 +252,16 @@
     post(task);
 }
 
+CREATE_BRIDGE0(fence) {
+    // Intentionally empty
+    return NULL;
+}
+
+void RenderProxy::fence() {
+    SETUP_TASK(fence);
+    postAndWait(task);
+}
+
 MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) {
     // TODO: Consider having a small pool of these to avoid alloc churn
     return new MethodInvokeRenderTask(method);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index f1ca534..fc51d21 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -78,6 +78,8 @@
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     ANDROID_API void destroyLayer(DeferredLayerUpdater* layer);
 
+    ANDROID_API void fence();
+
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;