Modify ActivityOptionsCompat

Modify ActivityOptionsCompat to use newer API implementations where
these are available.
Also add a static final field to AccessibilityNodeProviderCompat to make
it fully compatible with AccessibilityNodeProvider.
Both of the classes above can now serve as drop-in replacements for the
correspoding framework base classes.

Bug: 29093107
Change-Id: I7c38ee4b629bf276ebf5daec8f58a394ba149dce
diff --git a/compat/api/current.txt b/compat/api/current.txt
index e91e001..3c88e3b 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -55,13 +55,21 @@
 
   public class ActivityOptionsCompat {
     ctor protected ActivityOptionsCompat();
+    method public android.graphics.Rect getLaunchBounds();
+    method public static android.support.v4.app.ActivityOptionsCompat makeBasic();
+    method public static android.support.v4.app.ActivityOptionsCompat makeClipRevealAnimation(android.view.View, int, int, int, int);
     method public static android.support.v4.app.ActivityOptionsCompat makeCustomAnimation(android.content.Context, int, int);
     method public static android.support.v4.app.ActivityOptionsCompat makeScaleUpAnimation(android.view.View, int, int, int, int);
     method public static android.support.v4.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
     method public static android.support.v4.app.ActivityOptionsCompat makeSceneTransitionAnimation(android.app.Activity, android.support.v4.util.Pair<android.view.View, java.lang.String>...);
+    method public static android.support.v4.app.ActivityOptionsCompat makeTaskLaunchBehind();
     method public static android.support.v4.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+    method public void requestUsageTimeReport(android.app.PendingIntent);
+    method public android.support.v4.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect);
     method public android.os.Bundle toBundle();
     method public void update(android.support.v4.app.ActivityOptionsCompat);
+    field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
+    field public static final java.lang.String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
   }
 
   public final class AppOpsManagerCompat {
@@ -1825,6 +1833,7 @@
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat findFocus(int);
     method public java.lang.Object getProvider();
     method public boolean performAction(int, int, android.os.Bundle);
+    field public static final int HOST_VIEW_ID = -1; // 0xffffffff
   }
 
   public class AccessibilityRecordCompat {
diff --git a/compat/api21/android/support/v4/app/ActivityOptionsCompat21.java b/compat/api21/android/support/v4/app/ActivityOptionsCompat21.java
index d629e65..85673bd 100644
--- a/compat/api21/android/support/v4/app/ActivityOptionsCompat21.java
+++ b/compat/api21/android/support/v4/app/ActivityOptionsCompat21.java
@@ -16,8 +16,10 @@
 
 package android.support.v4.app;
 
-import android.app.ActivityOptions;
 import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.util.Pair;
 import android.view.View;
@@ -26,6 +28,24 @@
 
     private final ActivityOptions mActivityOptions;
 
+    public static ActivityOptionsCompat21 makeCustomAnimation(Context context,
+            int enterResId, int exitResId) {
+        return new ActivityOptionsCompat21(
+            ActivityOptions.makeCustomAnimation(context, enterResId, exitResId));
+    }
+
+    public static ActivityOptionsCompat21 makeScaleUpAnimation(View source,
+            int startX, int startY, int startWidth, int startHeight) {
+        return new ActivityOptionsCompat21(
+            ActivityOptions.makeScaleUpAnimation(source, startX, startY, startWidth, startHeight));
+    }
+
+    public static ActivityOptionsCompat21 makeThumbnailScaleUpAnimation(View source,
+            Bitmap thumbnail, int startX, int startY) {
+        return new ActivityOptionsCompat21(
+            ActivityOptions.makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY));
+    }
+
     public static ActivityOptionsCompat21 makeSceneTransitionAnimation(Activity activity,
             View sharedElement, String sharedElementName) {
         return new ActivityOptionsCompat21(
@@ -46,6 +66,11 @@
                 ActivityOptions.makeSceneTransitionAnimation(activity, pairs));
     }
 
+    public static ActivityOptionsCompat21 makeTaskLaunchBehind() {
+        return new ActivityOptionsCompat21(
+                ActivityOptions.makeTaskLaunchBehind());
+    }
+
     private ActivityOptionsCompat21(ActivityOptions activityOptions) {
         mActivityOptions = activityOptions;
     }
diff --git a/compat/api23/android/support/v4/app/ActivityOptionsCompat23.java b/compat/api23/android/support/v4/app/ActivityOptionsCompat23.java
new file mode 100644
index 0000000..b33fb11
--- /dev/null
+++ b/compat/api23/android/support/v4/app/ActivityOptionsCompat23.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.app;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.util.Pair;
+import android.view.View;
+
+class ActivityOptionsCompat23 {
+
+    private final ActivityOptions mActivityOptions;
+
+    public static ActivityOptionsCompat23 makeCustomAnimation(Context context,
+            int enterResId, int exitResId) {
+        return new ActivityOptionsCompat23(
+            ActivityOptions.makeCustomAnimation(context, enterResId, exitResId));
+    }
+
+    public static ActivityOptionsCompat23 makeScaleUpAnimation(View source,
+            int startX, int startY, int startWidth, int startHeight) {
+        return new ActivityOptionsCompat23(
+            ActivityOptions.makeScaleUpAnimation(source, startX, startY, startWidth, startHeight));
+    }
+
+    public static ActivityOptionsCompat23 makeThumbnailScaleUpAnimation(View source,
+            Bitmap thumbnail, int startX, int startY) {
+        return new ActivityOptionsCompat23(
+            ActivityOptions.makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY));
+    }
+
+    public static ActivityOptionsCompat23 makeSceneTransitionAnimation(Activity activity,
+            View sharedElement, String sharedElementName) {
+        return new ActivityOptionsCompat23(
+                ActivityOptions.makeSceneTransitionAnimation(activity, sharedElement,
+                        sharedElementName));
+    }
+
+    public static ActivityOptionsCompat23 makeSceneTransitionAnimation(Activity activity,
+            View[] sharedElements, String[] sharedElementNames) {
+        Pair[] pairs = null;
+        if (sharedElements != null) {
+            pairs = new Pair[sharedElements.length];
+            for (int i = 0; i < pairs.length; i++) {
+                pairs[i] = Pair.create(sharedElements[i], sharedElementNames[i]);
+            }
+        }
+        return new ActivityOptionsCompat23(
+                ActivityOptions.makeSceneTransitionAnimation(activity, pairs));
+    }
+
+    public static ActivityOptionsCompat23 makeClipRevealAnimation(View source,
+            int startX, int startY, int width, int height) {
+        return new ActivityOptionsCompat23(
+            ActivityOptions.makeClipRevealAnimation(source, startX, startY, width, height));
+    }
+
+    public static ActivityOptionsCompat23 makeTaskLaunchBehind() {
+        return new ActivityOptionsCompat23(
+                ActivityOptions.makeTaskLaunchBehind());
+    }
+
+    public static ActivityOptionsCompat23 makeBasic() {
+        return new ActivityOptionsCompat23(ActivityOptions.makeBasic());
+    }
+
+    private ActivityOptionsCompat23(ActivityOptions activityOptions) {
+        mActivityOptions = activityOptions;
+    }
+
+    public Bundle toBundle() {
+        return mActivityOptions.toBundle();
+    }
+
+    public void update(ActivityOptionsCompat23 otherOptions) {
+        mActivityOptions.update(otherOptions.mActivityOptions);
+    }
+
+    public void requestUsageTimeReport(PendingIntent receiver) {
+        mActivityOptions.requestUsageTimeReport(receiver);
+    }
+}
diff --git a/compat/api24/android/support/v4/app/ActivityOptionsCompat24.java b/compat/api24/android/support/v4/app/ActivityOptionsCompat24.java
new file mode 100644
index 0000000..4d166e4
--- /dev/null
+++ b/compat/api24/android/support/v4/app/ActivityOptionsCompat24.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.app;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.util.Pair;
+import android.view.View;
+
+class ActivityOptionsCompat24 {
+
+    public static ActivityOptionsCompat24 makeCustomAnimation(Context context,
+            int enterResId, int exitResId) {
+        return new ActivityOptionsCompat24(
+            ActivityOptions.makeCustomAnimation(context, enterResId, exitResId));
+    }
+
+    public static ActivityOptionsCompat24 makeScaleUpAnimation(View source,
+            int startX, int startY, int startWidth, int startHeight) {
+        return new ActivityOptionsCompat24(
+            ActivityOptions.makeScaleUpAnimation(source, startX, startY, startWidth, startHeight));
+    }
+
+    public static ActivityOptionsCompat24 makeThumbnailScaleUpAnimation(View source,
+            Bitmap thumbnail, int startX, int startY) {
+        return new ActivityOptionsCompat24(
+            ActivityOptions.makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY));
+    }
+
+    public static ActivityOptionsCompat24 makeSceneTransitionAnimation(Activity activity,
+            View sharedElement, String sharedElementName) {
+        return new ActivityOptionsCompat24(
+                ActivityOptions.makeSceneTransitionAnimation(activity, sharedElement,
+                        sharedElementName));
+    }
+
+    public static ActivityOptionsCompat24 makeSceneTransitionAnimation(Activity activity,
+            View[] sharedElements, String[] sharedElementNames) {
+        Pair[] pairs = null;
+        if (sharedElements != null) {
+            pairs = new Pair[sharedElements.length];
+            for (int i = 0; i < pairs.length; i++) {
+                pairs[i] = Pair.create(sharedElements[i], sharedElementNames[i]);
+            }
+        }
+        return new ActivityOptionsCompat24(
+                ActivityOptions.makeSceneTransitionAnimation(activity, pairs));
+    }
+
+    public static ActivityOptionsCompat24 makeClipRevealAnimation(View source,
+            int startX, int startY, int width, int height) {
+        return new ActivityOptionsCompat24(
+            ActivityOptions.makeClipRevealAnimation(source, startX, startY, width, height));
+    }
+
+    public static ActivityOptionsCompat24 makeTaskLaunchBehind() {
+        return new ActivityOptionsCompat24(
+                ActivityOptions.makeTaskLaunchBehind());
+    }
+
+    public static ActivityOptionsCompat24 makeBasic() {
+        return new ActivityOptionsCompat24(ActivityOptions.makeBasic());
+    }
+
+    private final ActivityOptions mActivityOptions;
+
+    private ActivityOptionsCompat24(ActivityOptions activityOptions) {
+        mActivityOptions = activityOptions;
+    }
+
+    public ActivityOptionsCompat24 setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
+        return new ActivityOptionsCompat24(mActivityOptions.setLaunchBounds(screenSpacePixelRect));
+    }
+
+    public Rect getLaunchBounds() {
+        return mActivityOptions.getLaunchBounds();
+    }
+
+    public Bundle toBundle() {
+        return mActivityOptions.toBundle();
+    }
+
+    public void update(ActivityOptionsCompat24 otherOptions) {
+        mActivityOptions.update(otherOptions.mActivityOptions);
+    }
+
+    public void requestUsageTimeReport(PendingIntent receiver) {
+        mActivityOptions.requestUsageTimeReport(receiver);
+    }
+}
diff --git a/compat/java/android/support/v4/app/ActivityOptionsCompat.java b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
index 6eb93c7..7d3d89e 100644
--- a/compat/java/android/support/v4/app/ActivityOptionsCompat.java
+++ b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
@@ -17,10 +17,13 @@
 package android.support.v4.app;
 
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.support.v4.util.Pair;
 import android.view.View;
 
@@ -30,6 +33,19 @@
  */
 public class ActivityOptionsCompat {
     /**
+     * A long in the extras delivered by {@link #requestUsageTimeReport} that contains
+     * the total time (in ms) the user spent in the app flow.
+     */
+    public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
+
+    /**
+     * A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
+     * detailed information about the time spent in each package associated with the app;
+     * each key is a package name, whose value is a long containing the time (in ms).
+     */
+    public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
+
+    /**
      * Create an ActivityOptions specifying a custom animation to run when the
      * activity is displayed.
      *
@@ -44,7 +60,16 @@
      */
     public static ActivityOptionsCompat makeCustomAnimation(Context context,
             int enterResId, int exitResId) {
-        if (Build.VERSION.SDK_INT >= 16) {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsImpl24(
+                ActivityOptionsCompat24.makeCustomAnimation(context, enterResId, exitResId));
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsImpl23(
+                ActivityOptionsCompat23.makeCustomAnimation(context, enterResId, exitResId));
+        } else if (Build.VERSION.SDK_INT >= 21) {
+            return new ActivityOptionsImpl21(
+                ActivityOptionsCompat21.makeCustomAnimation(context, enterResId, exitResId));
+        } else if (Build.VERSION.SDK_INT >= 16) {
             return new ActivityOptionsImplJB(
                 ActivityOptionsCompatJB.makeCustomAnimation(context, enterResId, exitResId));
         }
@@ -73,7 +98,19 @@
      */
     public static ActivityOptionsCompat makeScaleUpAnimation(View source,
             int startX, int startY, int startWidth, int startHeight) {
-        if (Build.VERSION.SDK_INT >= 16) {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsImpl24(
+                ActivityOptionsCompat24.makeScaleUpAnimation(source, startX, startY,
+                        startWidth, startHeight));
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsImpl23(
+                ActivityOptionsCompat23.makeScaleUpAnimation(source, startX, startY,
+                        startWidth, startHeight));
+        } else if (Build.VERSION.SDK_INT >= 21) {
+            return new ActivityOptionsImpl21(
+                ActivityOptionsCompat21.makeScaleUpAnimation(source, startX, startY,
+                        startWidth, startHeight));
+        } else if (Build.VERSION.SDK_INT >= 16) {
             return new ActivityOptionsImplJB(
                 ActivityOptionsCompatJB.makeScaleUpAnimation(source, startX, startY,
                         startWidth, startHeight));
@@ -82,6 +119,34 @@
     }
 
     /**
+     * Create an ActivityOptions specifying an animation where the new
+     * activity is revealed from a small originating area of the screen to
+     * its final full representation.
+     *
+     * @param source The View that the new activity is animating from.  This
+     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+     * @param startX The x starting location of the new activity, relative to <var>source</var>.
+     * @param startY The y starting location of the activity, relative to <var>source</var>.
+     * @param width The initial width of the new activity.
+     * @param height The initial height of the new activity.
+     * @return Returns a new ActivityOptions object that you can use to
+     * supply these options as the options Bundle when starting an activity.
+     */
+    public static ActivityOptionsCompat makeClipRevealAnimation(View source,
+            int startX, int startY, int width, int height) {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsImpl24(
+                ActivityOptionsCompat24.makeClipRevealAnimation(source, startX, startY,
+                        width, height));
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsImpl23(
+                ActivityOptionsCompat23.makeClipRevealAnimation(source, startX, startY,
+                        width, height));
+        }
+        return new ActivityOptionsCompat();
+    }
+
+    /**
      * Create an ActivityOptions specifying an animation where a thumbnail is
      * scaled from a given position to the new activity window that is being
      * started.
@@ -102,7 +167,19 @@
      */
     public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(View source,
             Bitmap thumbnail, int startX, int startY) {
-        if (Build.VERSION.SDK_INT >= 16) {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsImpl24(
+                ActivityOptionsCompat24.makeThumbnailScaleUpAnimation(source, thumbnail,
+                        startX, startY));
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsImpl23(
+                ActivityOptionsCompat23.makeThumbnailScaleUpAnimation(source, thumbnail,
+                        startX, startY));
+        } else if (Build.VERSION.SDK_INT >= 21) {
+            return new ActivityOptionsImpl21(
+                ActivityOptionsCompat21.makeThumbnailScaleUpAnimation(source, thumbnail,
+                        startX, startY));
+        } else if (Build.VERSION.SDK_INT >= 16) {
             return new ActivityOptionsImplJB(
                 ActivityOptionsCompatJB.makeThumbnailScaleUpAnimation(source, thumbnail,
                         startX, startY));
@@ -130,7 +207,15 @@
      */
     public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
             View sharedElement, String sharedElementName) {
-        if (Build.VERSION.SDK_INT >= 21) {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl24(
+                    ActivityOptionsCompat24.makeSceneTransitionAnimation(activity,
+                            sharedElement, sharedElementName));
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl23(
+                    ActivityOptionsCompat23.makeSceneTransitionAnimation(activity,
+                            sharedElement, sharedElementName));
+        } else if (Build.VERSION.SDK_INT >= 21) {
             return new ActivityOptionsCompat.ActivityOptionsImpl21(
                     ActivityOptionsCompat21.makeSceneTransitionAnimation(activity,
                             sharedElement, sharedElementName));
@@ -168,8 +253,55 @@
                     names[i] = sharedElements[i].second;
                 }
             }
+            if (Build.VERSION.SDK_INT >= 24) {
+                return new ActivityOptionsCompat.ActivityOptionsImpl24(
+                        ActivityOptionsCompat24.makeSceneTransitionAnimation(activity, views, names));
+            } else if (Build.VERSION.SDK_INT >= 23) {
+                return new ActivityOptionsCompat.ActivityOptionsImpl23(
+                        ActivityOptionsCompat23.makeSceneTransitionAnimation(activity, views, names));
+            } else {
+                return new ActivityOptionsCompat.ActivityOptionsImpl21(
+                        ActivityOptionsCompat21.makeSceneTransitionAnimation(activity, views, names));
+            }
+        }
+        return new ActivityOptionsCompat();
+    }
+
+    /**
+     * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
+     * presented to the user but will instead be only available through the recents task list.
+     * In addition, the new task wil be affiliated with the launching activity's task.
+     * Affiliated tasks are grouped together in the recents task list.
+     *
+     * <p>This behavior is not supported for activities with {@link
+     * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
+     * <code>singleInstance</code> or <code>singleTask</code>.
+     */
+    public static ActivityOptionsCompat makeTaskLaunchBehind() {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl24(
+                    ActivityOptionsCompat24.makeTaskLaunchBehind());
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl23(
+                    ActivityOptionsCompat23.makeTaskLaunchBehind());
+        } else if (Build.VERSION.SDK_INT >= 21) {
             return new ActivityOptionsCompat.ActivityOptionsImpl21(
-                    ActivityOptionsCompat21.makeSceneTransitionAnimation(activity, views, names));
+                    ActivityOptionsCompat21.makeTaskLaunchBehind());
+        }
+        return new ActivityOptionsCompat();
+    }
+
+    /**
+     * Create a basic ActivityOptions that has no special animation associated with it.
+     * Other options can still be set.
+     */
+    public static ActivityOptionsCompat makeBasic() {
+        if (Build.VERSION.SDK_INT >= 24) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl24(
+                    ActivityOptionsCompat24.makeBasic());
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            return new ActivityOptionsCompat.ActivityOptionsImpl23(
+                    ActivityOptionsCompat23.makeBasic());
         }
         return new ActivityOptionsCompat();
     }
@@ -217,10 +349,98 @@
         }
     }
 
+    private static class ActivityOptionsImpl23 extends ActivityOptionsCompat {
+        private final ActivityOptionsCompat23 mImpl;
+
+        ActivityOptionsImpl23(ActivityOptionsCompat23 impl) {
+            mImpl = impl;
+        }
+
+        @Override
+        public Bundle toBundle() {
+            return mImpl.toBundle();
+        }
+
+        @Override
+        public void update(ActivityOptionsCompat otherOptions) {
+            if (otherOptions instanceof ActivityOptionsCompat.ActivityOptionsImpl23) {
+                ActivityOptionsCompat.ActivityOptionsImpl23
+                        otherImpl = (ActivityOptionsCompat.ActivityOptionsImpl23)otherOptions;
+                mImpl.update(otherImpl.mImpl);
+            }
+        }
+
+        @Override
+        public void requestUsageTimeReport(PendingIntent receiver) {
+            mImpl.requestUsageTimeReport(receiver);
+        }
+    }
+
+    private static class ActivityOptionsImpl24 extends ActivityOptionsCompat {
+        private final ActivityOptionsCompat24 mImpl;
+
+        ActivityOptionsImpl24(ActivityOptionsCompat24 impl) {
+            mImpl = impl;
+        }
+
+        @Override
+        public Bundle toBundle() {
+            return mImpl.toBundle();
+        }
+
+        @Override
+        public void update(ActivityOptionsCompat otherOptions) {
+            if (otherOptions instanceof ActivityOptionsCompat.ActivityOptionsImpl24) {
+                ActivityOptionsCompat.ActivityOptionsImpl24
+                        otherImpl = (ActivityOptionsCompat.ActivityOptionsImpl24)otherOptions;
+                mImpl.update(otherImpl.mImpl);
+            }
+        }
+
+        @Override
+        public ActivityOptionsCompat setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
+            return new ActivityOptionsImpl24(mImpl.setLaunchBounds(screenSpacePixelRect));
+        }
+
+        @Override
+        public Rect getLaunchBounds() {
+            return mImpl.getLaunchBounds();
+        }
+
+        @Override
+        public void requestUsageTimeReport(PendingIntent receiver) {
+            mImpl.requestUsageTimeReport(receiver);
+        }
+    }
+
     protected ActivityOptionsCompat() {
     }
 
     /**
+     * Sets the bounds (window size) that the activity should be launched in.
+     * Rect position should be provided in pixels and in screen coordinates.
+     * Set to null explicitly for fullscreen.
+     * <p>
+     * <strong>NOTE:<strong/> This value is ignored on devices that don't have
+     * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
+     * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
+     * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
+     */
+    public ActivityOptionsCompat setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
+        return null;
+    }
+
+    /**
+     * Returns the bounds that should be used to launch the activity.
+     * @see #setLaunchBounds(Rect)
+     * @return Bounds used to launch the activity.
+     */
+    @Nullable
+    public Rect getLaunchBounds() {
+        return null;
+    }
+
+    /**
      * Returns the created options as a Bundle, which can be passed to
      * {@link ActivityCompat#startActivity(android.app.Activity, android.content.Intent, android.os.Bundle)}.
      * Note that the returned Bundle is still owned by the ActivityOptions
@@ -239,4 +459,32 @@
     public void update(ActivityOptionsCompat otherOptions) {
         // Do nothing.
     }
+
+    /**
+     * Ask the the system track that time the user spends in the app being launched, and
+     * report it back once done.  The report will be sent to the given receiver, with
+     * the extras {@link #EXTRA_USAGE_TIME_REPORT} and {@link #EXTRA_USAGE_TIME_REPORT_PACKAGES}
+     * filled in.
+     *
+     * <p>The time interval tracked is from launching this activity until the user leaves
+     * that activity's flow.  They are considered to stay in the flow as long as
+     * new activities are being launched or returned to from the original flow,
+     * even if this crosses package or task boundaries.  For example, if the originator
+     * starts an activity to view an image, and while there the user selects to share,
+     * which launches their email app in a new task, and they complete the share, the
+     * time during that entire operation will be included until they finally hit back from
+     * the original image viewer activity.</p>
+     *
+     * <p>The user is considered to complete a flow once they switch to another
+     * activity that is not part of the tracked flow.  This may happen, for example, by
+     * using the notification shade, launcher, or recents to launch or switch to another
+     * app.  Simply going in to these navigation elements does not break the flow (although
+     * the launcher and recents stops time tracking of the session); it is the act of
+     * going somewhere else that completes the tracking.</p>
+     *
+     * @param receiver A broadcast receiver that willl receive the report.
+     */
+    public void requestUsageTimeReport(PendingIntent receiver) {
+        // Do nothing.
+    }
 }
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
index e6da5f1..42a883b 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
@@ -131,6 +131,11 @@
         }
     }
 
+    /**
+     * The virtual id for the hosting View.
+     */
+    public static final int HOST_VIEW_ID = -1;
+
     private static final AccessibilityNodeProviderImpl IMPL;
 
     private final Object mProvider;
@@ -172,7 +177,7 @@
     /**
      * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual view,
      * i.e. a descendant of the host View, with the given <code>virtualViewId</code>
-     * or the host View itself if <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     * or the host View itself if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
      * <p>
      * A virtual descendant is an imaginary View that is reported as a part of the view
      * hierarchy for accessibility purposes. This enables custom views that draw complex
@@ -198,7 +203,7 @@
     /**
      * Performs an accessibility action on a virtual view, i.e. a descendant of the
      * host View, with the given <code>virtualViewId</code> or the host View itself
-     * if <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
      *
      * @param virtualViewId A client defined virtual view id.
      * @param action The action to perform.
@@ -216,7 +221,7 @@
      * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case insensitive
      * containment. The search is relative to the virtual view, i.e. a descendant of the
      * host View, with the given <code>virtualViewId</code> or the host View itself
-     * <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     * <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
      *
      * @param virtualViewId A client defined virtual view id which defined
      *     the root of the tree in which to perform the search.