Invalidate display lists immediately when views are removed/added quickly

The deferred invalidation of display list could cause problems with
view like TextureView who destroy resources when detached from the
window but only recreate them later at draw time. This would cause
temporary flashes or other visual glitches on screen.

Change-Id: I018488ba09743df21c6434ea610813014fb80a85
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8053238..55f2d9d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11077,22 +11077,30 @@
         if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
             mParent.requestTransparentRegion(this);
         }
+
         if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
             initialAwakenScrollBars();
             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
+
         jumpDrawablesToCurrentState();
+
         // Order is important here: LayoutDirection MUST be resolved before Padding
         // and TextDirection
         resolveLayoutDirection();
         resolvePadding();
         resolveTextDirection();
         resolveTextAlignment();
+
         clearAccessibilityFocus();
         if (isFocused()) {
             InputMethodManager imm = InputMethodManager.peekInstance();
             imm.focusIn(this);
         }
+
+        if (mAttachInfo != null && mDisplayList != null) {
+            mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
+        }
     }
 
     /**
@@ -11313,7 +11321,7 @@
 
         if (mAttachInfo != null) {
             if (mDisplayList != null) {
-                mAttachInfo.mViewRootImpl.invalidateDisplayList(mDisplayList);
+                mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
             }
             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
         } else {
@@ -12007,7 +12015,6 @@
 
             boolean caching = false;
             final HardwareCanvas canvas = displayList.start();
-            int restoreCount = 0;
             int width = mRight - mLeft;
             int height = mBottom - mTop;
 
@@ -12640,10 +12647,6 @@
         return more;
     }
 
-    void setDisplayListProperties() {
-        setDisplayListProperties(mDisplayList);
-    }
-
     /**
      * This method is called by getDisplayList() when a display list is created or re-rendered.
      * It sets or resets the current value of all properties on that display list (resetting is
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ec6bd81..5f295cb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4412,14 +4412,23 @@
         mInvalidateOnAnimationRunnable.addViewRect(info);
     }
 
-    public void invalidateDisplayList(DisplayList displayList) {
+    public void enqueueDisplayList(DisplayList displayList) {
         mDisplayLists.add(displayList);
 
         mHandler.removeMessages(MSG_INVALIDATE_DISPLAY_LIST);
         Message msg = mHandler.obtainMessage(MSG_INVALIDATE_DISPLAY_LIST);
         mHandler.sendMessage(msg);
     }
-    
+
+    public void dequeueDisplayList(DisplayList displayList) {
+        if (mDisplayLists.remove(displayList)) {
+            displayList.invalidate();
+            if (mDisplayLists.size() == 0) {
+                mHandler.removeMessages(MSG_INVALIDATE_DISPLAY_LIST);
+            }
+        }
+    }
+
     public void cancelInvalidate(View view) {
         mHandler.removeMessages(MSG_INVALIDATE, view);
         // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning