Fix invalidation bug with INVISIBLE views.

There was a bug in the invalidation code that prevented some
animations fropm starting. An INVISIBLE view would mark some dirty
flags then propagate the invaliation up the parent hierarchy. This would
cause a redraw of the hierarchy, but would not include the invisible
view (invisible children do not get drawn). Thus the flags wouldn't get cleared.

Later, an animation to fade the view in (making it VISIBLE on start) would
be started on the view. But the invalidation triggered by that animation would
not propagate because the invisible view would see that it was already
invalidated, and wouldn't send the message along. No invalidation means no drawing,
so the animation wouldn't start because the invalidation didn't make it's way up to the
top and the child's parent did not redraw.

The fix is to noop the invalidate() call for GONE/INVISIBLE views which do not
have animations set on them. Making these views VISIBLE later will trigger
an invalidation, as will starting an animation on them, so the behavior should
not change except for the buggy situation.

Change-Id: I7a26a4bc7823f08fef56e52648e77ca256df6858
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index abd9ad6..8006185 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8087,6 +8087,11 @@
             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
         }
 
+        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null) {
+            // Noop for views which are not visible and which are not running an animation. They
+            // will not get drawn and they should not set dirty flags as if they will be drawn
+            return;
+        }
         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
@@ -8130,6 +8135,11 @@
             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
         }
 
+        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null) {
+            // Noop for views which are not visible and which are not running an animation. They
+            // will not get drawn and they should not set dirty flags as if they will be drawn
+            return;
+        }
         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
@@ -8182,6 +8192,11 @@
             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
         }
 
+        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null) {
+            // Noop for views which are not visible and which are not running an animation. They
+            // will not get drawn and they should not set dirty flags as if they will be drawn
+            return;
+        }
         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
                 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
                 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
@@ -8217,6 +8232,11 @@
      * @hide
      */
     public void fastInvalidate() {
+        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null) {
+            // Noop for views which are not visible and which are not running an animation. They
+            // will not get drawn and they should not set dirty flags as if they will be drawn
+            return;
+        }
         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
             (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
             (mPrivateFlags & INVALIDATED) != INVALIDATED) {