Resume RT-animations after a pauseSurface

Bug: 18203577

The issue occurs as a result of performTraversals() both doing
a window relayout call *and* early-returning because it's not dirty.

To fix this pauseSurface() returns whether or not the RT-side is
"dirty" to force ViewRootImpl to do a draw even if mDirty is
otherwise empty.

Change-Id: I534f367e75d18d273ebf14df3927f5c464ef6bef
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 904e33f..c5c3f83 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -235,7 +235,7 @@
      * or not the surface used by the HardwareRenderer will be changing. It
      * Suspends any rendering into the surface, but will not do any destruction
      */
-    abstract void pauseSurface(Surface surface);
+    abstract boolean pauseSurface(Surface surface);
 
     /**
      * Destroys all hardware rendering resources associated with the specified
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 131c039..14b950f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -155,8 +155,8 @@
     }
 
     @Override
-    void pauseSurface(Surface surface) {
-        nPauseSurface(mNativeProxy, surface);
+    boolean pauseSurface(Surface surface) {
+        return nPauseSurface(mNativeProxy, surface);
     }
 
     @Override
@@ -494,7 +494,7 @@
 
     private static native boolean nInitialize(long nativeProxy, Surface window);
     private static native void nUpdateSurface(long nativeProxy, Surface window);
-    private static native void nPauseSurface(long nativeProxy, Surface window);
+    private static native boolean nPauseSurface(long nativeProxy, Surface window);
     private static native void nSetup(long nativeProxy, int width, int height,
             float lightX, float lightY, float lightZ, float lightRadius,
             int ambientShadowAlpha, int spotShadowAlpha);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b12c747..34c27d7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1493,7 +1493,11 @@
                     // relayoutWindow may decide to destroy mSurface. As that decision
                     // happens in WindowManager service, we need to be defensive here
                     // and stop using the surface in case it gets destroyed.
-                    mAttachInfo.mHardwareRenderer.pauseSurface(mSurface);
+                    if (mAttachInfo.mHardwareRenderer.pauseSurface(mSurface)) {
+                        // Animations were running so we need to push a frame
+                        // to resume them
+                        mDirty.set(0, 0, mWidth, mHeight);
+                    }
                 }
                 final int surfaceGenerationId = mSurface.getGenerationId();
                 relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 6219956..b9d849c 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -270,14 +270,14 @@
     proxy->updateSurface(window);
 }
 
-static void android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
+static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     sp<ANativeWindow> window;
     if (jsurface) {
         window = android_view_Surface_getNativeWindow(env, jsurface);
     }
-    proxy->pauseSurface(window);
+    return proxy->pauseSurface(window);
 }
 
 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
@@ -429,7 +429,7 @@
     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
-    { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
+    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
     { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index aa32541..75bd067 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -123,8 +123,8 @@
     setSurface(window);
 }
 
-void CanvasContext::pauseSurface(ANativeWindow* window) {
-    stopDrawing();
+bool CanvasContext::pauseSurface(ANativeWindow* window) {
+    return mRenderThread.removeFrameCallback(this);
 }
 
 // TODO: don't pass viewport size, it's automatic via EGL
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 435244e..0cc2c7c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -67,7 +67,7 @@
 
     bool initialize(ANativeWindow* window);
     void updateSurface(ANativeWindow* window);
-    void pauseSurface(ANativeWindow* window);
+    bool pauseSurface(ANativeWindow* window);
     bool hasSurface() { return mNativeWindow.get(); }
 
     void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5d55ea6..6d063a4 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -156,15 +156,14 @@
 }
 
 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
-    args->context->pauseSurface(args->window);
-    return NULL;
+    return (void*) args->context->pauseSurface(args->window);
 }
 
-void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
+bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
     SETUP_TASK(pauseSurface);
     args->context = mContext;
     args->window = window.get();
-    postAndWait(task);
+    return (bool) postAndWait(task);
 }
 
 CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height,
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 4989b14..fd1fe05 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,7 +69,7 @@
 
     ANDROID_API bool initialize(const sp<ANativeWindow>& window);
     ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
-    ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
+    ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
     ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     ANDROID_API void setOpaque(bool opaque);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index f887103..38cb4cd 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -314,9 +314,11 @@
     mPendingRegistrationFrameCallbacks.insert(callback);
 }
 
-void RenderThread::removeFrameCallback(IFrameCallback* callback) {
-    mFrameCallbacks.erase(callback);
-    mPendingRegistrationFrameCallbacks.erase(callback);
+bool RenderThread::removeFrameCallback(IFrameCallback* callback) {
+    size_t erased;
+    erased = mFrameCallbacks.erase(callback);
+    erased |= mPendingRegistrationFrameCallbacks.erase(callback);
+    return erased;
 }
 
 void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index c461f3a..4126d02 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -80,7 +80,7 @@
 
     // Mimics android.view.Choreographer
     void postFrameCallback(IFrameCallback* callback);
-    void removeFrameCallback(IFrameCallback* callback);
+    bool removeFrameCallback(IFrameCallback* callback);
     // If the callback is currently registered, it will be pushed back until
     // the next vsync. If it is not currently registered this does nothing.
     void pushBackFrameCallback(IFrameCallback* callback);