Only dispatch window visibility aggregation for targetSdk >= N

Some existing apps treat drawable visibility notifications as a signal
to crossfade from a placeholder to the new image for the purposes of
scrolling onscreen via a recycling collection view or similar. Since
dispatchVisibilityAggregated is now called for window visibility
changes and ImageView informs its drawable of the visiblity change,
the extra call triggers a repeat fade-in in some existing apps when
you return them to visibility.

These apps should pay attention to the second parameter of
Drawable#setVisible, which signals that animations should not restart
in response to a visibility change. Updating to targetSdkVersion=24+
will enable the new behavior.

Bug 30216207

Change-Id: I27ce9f09bc7544863f7f7980c273650949db21cc
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4dc1009..7494b94 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -52,6 +52,7 @@
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
@@ -1540,7 +1541,15 @@
         if (viewVisibilityChanged) {
             mAttachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
-            host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
+
+            // Prior to N we didn't have dispatchVisibilityAggregated to give a more accurate
+            // view into when views are visible to the user or not. ImageView never dealt with
+            // telling its drawable about window visibility, among other things. Some apps cause
+            // an additional crossfade animation when windows become visible if they get this
+            // additional call, so only send it to new apps to avoid new visual jank.
+            if (host.getContext().getApplicationInfo().targetSdkVersion >= VERSION_CODES.N) {
+                host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
+            }
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 endDragResizing();
                 destroyHardwareResources();