Add a method and interface to SharedElementCallback

Add the onSharedElementsArrived method and the
OnSharedElementsReadyListener interface to the support library version
of the SharedElementCallback abstract class for better coverage.

Bug: 29263447
Change-Id: Ib0d9a366f4777afeee7609e8c92446f6104908cb
diff --git a/compat/api/current.txt b/compat/api/current.txt
index 405f2e5..0610821 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -549,6 +549,11 @@
     method public void onRejectSharedElements(java.util.List<android.view.View>);
     method public void onSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
     method public void onSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+    method public void onSharedElementsArrived(java.util.List<java.lang.String>, java.util.List<android.view.View>, android.support.v4.app.SharedElementCallback.OnSharedElementsReadyListener);
+  }
+
+  public static abstract interface SharedElementCallback.OnSharedElementsReadyListener {
+    method public abstract void onSharedElementsReady();
   }
 
 }
diff --git a/compat/api23/android/support/v4/app/ActivityCompatApi23.java b/compat/api23/android/support/v4/app/ActivityCompatApi23.java
index 40df982..5ed84df 100644
--- a/compat/api23/android/support/v4/app/ActivityCompatApi23.java
+++ b/compat/api23/android/support/v4/app/ActivityCompatApi23.java
@@ -17,10 +17,23 @@
 package android.support.v4.app;
 
 import android.app.Activity;
+import android.app.SharedElementCallback;
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.os.Parcelable;
+import android.view.View;
+
+import java.util.List;
+import java.util.Map;
 
 class ActivityCompatApi23 {
+    public interface OnSharedElementsReadyListenerBridge {
+        void onSharedElementsReady();
+    }
+
     public interface RequestPermissionsRequestCodeValidator {
-        public void validateRequestPermissionsRequestCode(int requestCode);
+        void validateRequestPermissionsRequestCode(int requestCode);
     }
 
     public static void requestPermissions(Activity activity, String[] permissions,
@@ -36,4 +49,84 @@
             String permission) {
         return activity.shouldShowRequestPermissionRationale(permission);
     }
+
+    public static void setEnterSharedElementCallback(Activity activity,
+            SharedElementCallback23 callback) {
+        activity.setEnterSharedElementCallback(createCallback(callback));
+    }
+
+    public static void setExitSharedElementCallback(Activity activity,
+            SharedElementCallback23 callback) {
+        activity.setExitSharedElementCallback(createCallback(callback));
+    }
+
+    private static SharedElementCallback createCallback(SharedElementCallback23 callback) {
+        SharedElementCallback newListener = null;
+        if (callback != null) {
+            newListener = new SharedElementCallbackImpl(callback);
+        }
+        return newListener;
+    }
+
+    public abstract static class SharedElementCallback23
+            extends ActivityCompat21.SharedElementCallback21 {
+        public abstract void onSharedElementsArrived(List<String> sharedElementNames,
+                List<View> sharedElements, OnSharedElementsReadyListenerBridge listener);
+    }
+
+    private static class SharedElementCallbackImpl extends SharedElementCallback {
+        private SharedElementCallback23 mCallback;
+
+        public SharedElementCallbackImpl(SharedElementCallback23 callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void onSharedElementStart(List<String> sharedElementNames,
+                List<View> sharedElements, List<View> sharedElementSnapshots) {
+            mCallback.onSharedElementStart(sharedElementNames, sharedElements,
+                    sharedElementSnapshots);
+        }
+
+        @Override
+        public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements,
+                List<View> sharedElementSnapshots) {
+            mCallback.onSharedElementEnd(sharedElementNames, sharedElements,
+                    sharedElementSnapshots);
+        }
+
+        @Override
+        public void onRejectSharedElements(List<View> rejectedSharedElements) {
+            mCallback.onRejectSharedElements(rejectedSharedElements);
+        }
+
+        @Override
+        public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
+            mCallback.onMapSharedElements(names, sharedElements);
+        }
+
+        @Override
+        public Parcelable onCaptureSharedElementSnapshot(View sharedElement,
+                Matrix viewToGlobalMatrix, RectF screenBounds) {
+            return mCallback.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix,
+                            screenBounds);
+        }
+
+        @Override
+        public View onCreateSnapshotView(Context context, Parcelable snapshot) {
+            return mCallback.onCreateSnapshotView(context, snapshot);
+        }
+
+        @Override
+        public void onSharedElementsArrived(List<String> sharedElementNames,
+                List<View> sharedElements, final OnSharedElementsReadyListener listener) {
+            mCallback.onSharedElementsArrived(sharedElementNames, sharedElements,
+                    new OnSharedElementsReadyListenerBridge() {
+                        @Override
+                        public void onSharedElementsReady() {
+                            listener.onSharedElementsReady();
+                        }
+                    });
+        }
+    }
 }
diff --git a/compat/java/android/support/v4/app/ActivityCompat.java b/compat/java/android/support/v4/app/ActivityCompat.java
index c130372..ac3b991 100644
--- a/compat/java/android/support/v4/app/ActivityCompat.java
+++ b/compat/java/android/support/v4/app/ActivityCompat.java
@@ -34,7 +34,6 @@
 import android.support.v4.content.ContextCompat;
 import android.view.View;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -68,7 +67,7 @@
          *
          * @see #requestPermissions(android.app.Activity, String[], int)
          */
-        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+        void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                 @NonNull int[] grantResults);
     }
 
@@ -267,7 +266,9 @@
      */
     public static void setEnterSharedElementCallback(Activity activity,
             SharedElementCallback callback) {
-        if (Build.VERSION.SDK_INT >= 21) {
+        if (Build.VERSION.SDK_INT >= 23) {
+            ActivityCompatApi23.setEnterSharedElementCallback(activity, createCallback23(callback));
+        } else if (Build.VERSION.SDK_INT >= 21) {
             ActivityCompat21.setEnterSharedElementCallback(activity, createCallback(callback));
         }
     }
@@ -283,7 +284,9 @@
      */
     public static void setExitSharedElementCallback(Activity activity,
             SharedElementCallback callback) {
-        if (Build.VERSION.SDK_INT >= 21) {
+        if (Build.VERSION.SDK_INT >= 23) {
+            ActivityCompatApi23.setExitSharedElementCallback(activity, createCallback23(callback));
+        } else if (Build.VERSION.SDK_INT >= 21) {
             ActivityCompat21.setExitSharedElementCallback(activity, createCallback(callback));
         }
     }
@@ -419,6 +422,15 @@
         return newCallback;
     }
 
+    private static ActivityCompatApi23.SharedElementCallback23 createCallback23(
+            SharedElementCallback callback) {
+        ActivityCompatApi23.SharedElementCallback23 newCallback = null;
+        if (callback != null) {
+            newCallback = new ActivityCompat.SharedElementCallback23Impl(callback);
+        }
+        return newCallback;
+    }
+
     private static class SharedElementCallback21Impl
             extends ActivityCompat21.SharedElementCallback21 {
 
@@ -464,4 +476,63 @@
             return mCallback.onCreateSnapshotView(context, snapshot);
         }
     }
+
+    private static class SharedElementCallback23Impl
+            extends ActivityCompatApi23.SharedElementCallback23 {
+
+        private SharedElementCallback mCallback;
+
+        public SharedElementCallback23Impl(SharedElementCallback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void onSharedElementStart(List<String> sharedElementNames,
+                List<View> sharedElements, List<View> sharedElementSnapshots) {
+            mCallback.onSharedElementStart(sharedElementNames, sharedElements,
+                    sharedElementSnapshots);
+        }
+
+        @Override
+        public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements,
+                List<View> sharedElementSnapshots) {
+            mCallback.onSharedElementEnd(sharedElementNames, sharedElements,
+                    sharedElementSnapshots);
+        }
+
+        @Override
+        public void onRejectSharedElements(List<View> rejectedSharedElements) {
+            mCallback.onRejectSharedElements(rejectedSharedElements);
+        }
+
+        @Override
+        public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
+            mCallback.onMapSharedElements(names, sharedElements);
+        }
+
+        @Override
+        public Parcelable onCaptureSharedElementSnapshot(View sharedElement,
+                Matrix viewToGlobalMatrix, RectF screenBounds) {
+            return mCallback.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix,
+                    screenBounds);
+        }
+
+        @Override
+        public View onCreateSnapshotView(Context context, Parcelable snapshot) {
+            return mCallback.onCreateSnapshotView(context, snapshot);
+        }
+
+        @Override
+        public void onSharedElementsArrived(List<String> sharedElementNames,
+                List<View> sharedElements,
+                final ActivityCompatApi23.OnSharedElementsReadyListenerBridge listener) {
+            mCallback.onSharedElementsArrived(sharedElementNames, sharedElements,
+                    new SharedElementCallback.OnSharedElementsReadyListener() {
+                        @Override
+                        public void onSharedElementsReady() {
+                            listener.onSharedElementsReady();
+                        }
+                    });
+        }
+    }
 }
diff --git a/compat/java/android/support/v4/app/SharedElementCallback.java b/compat/java/android/support/v4/app/SharedElementCallback.java
index 8beb29d..5c64762 100644
--- a/compat/java/android/support/v4/app/SharedElementCallback.java
+++ b/compat/java/android/support/v4/app/SharedElementCallback.java
@@ -16,7 +16,6 @@
 package android.support.v4.app;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
@@ -281,4 +280,41 @@
         return view;
     }
 
+    /**
+     * Called during an Activity Transition when the shared elements have arrived at the
+     * final location and are ready to be transferred. This method is called for both the
+     * source and destination Activities.
+     * <p>
+     * When the shared elements are ready to be transferred,
+     * {@link OnSharedElementsReadyListener#onSharedElementsReady()}
+     * must be called to trigger the transfer.
+     * <p>
+     * The default behavior is to trigger the transfer immediately.
+     *
+     * @param sharedElementNames The names of the shared elements that are being transferred..
+     * @param sharedElements The shared elements that are part of the View hierarchy.
+     * @param listener The listener to call when the shared elements are ready to be hidden
+     *                 in the source Activity or shown in the destination Activity.
+     */
+    public void onSharedElementsArrived(List<String> sharedElementNames,
+            List<View> sharedElements, OnSharedElementsReadyListener listener) {
+        listener.onSharedElementsReady();
+    }
+
+    /**
+     * Listener to be called after {@link
+     * SharedElementCallback#onSharedElementsArrived(List, List, OnSharedElementsReadyListener)}
+     * when the shared elements are ready to be hidden in the source Activity and shown in the
+     * destination Activity.
+     */
+    public interface OnSharedElementsReadyListener {
+
+        /**
+         * Call this method during or after the OnSharedElementsReadyListener has been received
+         * in {@link SharedElementCallback#onSharedElementsArrived(List, List,
+         * OnSharedElementsReadyListener)} to indicate that the shared elements are ready to be
+         * hidden in the source and shown in the destination Activity.
+         */
+        void onSharedElementsReady();
+    }
 }
diff --git a/fragment/api/current.txt b/fragment/api/current.txt
index 63c5149..68f66c3 100644
--- a/fragment/api/current.txt
+++ b/fragment/api/current.txt
@@ -364,6 +364,11 @@
     method public void onRejectSharedElements(java.util.List<android.view.View>);
     method public void onSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
     method public void onSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+    method public void onSharedElementsArrived(java.util.List<java.lang.String>, java.util.List<android.view.View>, android.support.v4.app.SharedElementCallback.OnSharedElementsReadyListener);
+  }
+
+  public static abstract interface SharedElementCallback.OnSharedElementsReadyListener {
+    method public abstract void onSharedElementsReady();
   }
 
 }