Updates documentation for MessagingStyle constructor
am: 5c45c3ad1a

Change-Id: Iebc4a18ca6e07cfc46f4d35f756343e7aabc8f08
diff --git a/compat/java/android/support/v4/app/ActivityCompat.java b/compat/java/android/support/v4/app/ActivityCompat.java
index c30e49d..3888be9 100644
--- a/compat/java/android/support/v4/app/ActivityCompat.java
+++ b/compat/java/android/support/v4/app/ActivityCompat.java
@@ -29,6 +29,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcelable;
+import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.content.ContextCompat;
@@ -330,8 +331,8 @@
      * to grant and which to reject. Hence, you should be prepared that your activity
      * may be paused and resumed. Further, granting some permissions may require
      * a restart of you application. In such a case, the system will recreate the
-     * activity stack before delivering the result to your onRequestPermissionsResult(
-     * int, String[], int[]).
+     * activity stack before delivering the result to your
+     * {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
      * </p>
      * <p>
      * When checking whether you have a permission you should use {@link
@@ -343,18 +344,30 @@
      * can be useful if the way your app uses the data guarded by the permissions
      * changes significantly.
      * </p>
+     * <p>
+     * You cannot request a permission if your activity sets {@link
+     * android.R.attr#noHistory noHistory} to <code>true</code> in the manifest
+     * because in this case the activity would not receive result callbacks including
+     * {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
+     * </p>
+     * <p>
+     * The <a href="http://developer.android.com/samples/RuntimePermissions/index.html">
+     * RuntimePermissions</a> sample app demonstrates how to use this method to
+     * request permissions at run time.
+     * </p>
      *
      * @param activity The target activity.
-     * @param permissions The requested permissions.
+     * @param permissions The requested permissions. Must me non-null and not empty.
      * @param requestCode Application specific request code to match with a result
-     *    reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(
-     *    int, String[], int[])}.
+     *    reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
+     *    Should be >= 0.
      *
+     * @see OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])
      * @see #checkSelfPermission(android.content.Context, String)
      * @see #shouldShowRequestPermissionRationale(android.app.Activity, String)
      */
     public static void requestPermissions(final @NonNull Activity activity,
-            final @NonNull String[] permissions, final int requestCode) {
+            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
         if (Build.VERSION.SDK_INT >= 23) {
             ActivityCompatApi23.requestPermissions(activity, permissions, requestCode);
         } else if (activity instanceof OnRequestPermissionsResultCallback) {
diff --git a/compat/java/android/support/v4/content/ModernAsyncTask.java b/compat/java/android/support/v4/content/ModernAsyncTask.java
index bb80bb6..7e95da6 100644
--- a/compat/java/android/support/v4/content/ModernAsyncTask.java
+++ b/compat/java/android/support/v4/content/ModernAsyncTask.java
@@ -16,6 +16,15 @@
 
 package android.support.v4.content;
 
+import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.support.annotation.RestrictTo;
+
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
@@ -30,15 +39,6 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import android.os.Binder;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.support.annotation.RestrictTo;
-
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
-
 /**
  * Copy of the required parts of {@link android.os.AsyncTask} from Android 3.0 that is
  * needed to support AsyncTaskLoader.  We use this rather than the one from the platform
@@ -86,7 +86,8 @@
 
     private volatile Status mStatus = Status.PENDING;
 
-    final AtomicBoolean mTaskInvoked = new AtomicBoolean();
+    private final AtomicBoolean mCancelled = new AtomicBoolean();
+    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 
     /**
      * Indicates the current status of the task. Each status will be set only once
@@ -136,6 +137,9 @@
                     //noinspection unchecked
                     result = doInBackground(mParams);
                     Binder.flushPendingCommands();
+                } catch (Throwable tr) {
+                    mCancelled.set(true);
+                    throw tr;
                 } finally {
                     postResult(result);
                 }
@@ -289,7 +293,7 @@
      * @see #cancel(boolean)
      */
     public final boolean isCancelled() {
-        return mFuture.isCancelled();
+        return mCancelled.get();
     }
 
     /**
@@ -322,6 +326,7 @@
      * @see #onCancelled(Object)
      */
     public final boolean cancel(boolean mayInterruptIfRunning) {
+        mCancelled.set(true);
         return mFuture.cancel(mayInterruptIfRunning);
     }
 
diff --git a/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java b/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
index fc144c5..3e13f44 100644
--- a/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
+++ b/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.fail;
 
+import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -26,6 +27,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
@@ -76,4 +78,53 @@
             fail("onCancelled not called!");
         }
     }
+
+    /**
+     * Test to ensure that onCancelled is always called instead of onPostExecute when the exception
+     * is not suppressed by cancelling the task.
+     *
+     * @throws Throwable
+     */
+    @LargeTest
+    @Test
+    public void testException() throws Throwable {
+        final CountDownLatch calledOnCancelled = new CountDownLatch(1);
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mModernAsyncTask = new ModernAsyncTask() {
+                    @Override
+                    protected Object doInBackground(Object[] params) {
+                        throw new RuntimeException();
+                    }
+
+                    @Override
+                    protected void onPostExecute(Object o) {
+                        fail("onPostExecute should not be called");
+                    }
+
+                    @Override
+                    protected void onCancelled(Object o) {
+                        calledOnCancelled.countDown();
+                    }
+                };
+            }
+        });
+
+        mModernAsyncTask.executeOnExecutor(new Executor() {
+            @Override
+            public void execute(@NonNull Runnable command) {
+                try {
+                    command.run();
+                    fail("Exception not thrown");
+                } catch (Throwable tr) {
+                    // expected
+                }
+            }
+        });
+
+        if (!calledOnCancelled.await(5, TimeUnit.SECONDS)) {
+            fail("onCancelled not called");
+        }
+    }
 }
diff --git a/design/src/android/support/design/widget/CoordinatorLayout.java b/design/src/android/support/design/widget/CoordinatorLayout.java
index f916e5f..9566934 100644
--- a/design/src/android/support/design/widget/CoordinatorLayout.java
+++ b/design/src/android/support/design/widget/CoordinatorLayout.java
@@ -1309,6 +1309,12 @@
     }
 
     private void offsetChildByInset(final View child, final Rect inset, final int layoutDirection) {
+        if (!ViewCompat.isLaidOut(child)) {
+            // The view has not been laid out yet,
+            // so we can't obtain its bounds.
+            return;
+        }
+
         final LayoutParams lp = (LayoutParams) child.getLayoutParams();
         final int absDodgeInsetEdges = GravityCompat.getAbsoluteGravity(lp.dodgeInsetEdges,
                 layoutDirection);
diff --git a/design/src/android/support/design/widget/TextInputLayout.java b/design/src/android/support/design/widget/TextInputLayout.java
index 40adf2d..3355956 100644
--- a/design/src/android/support/design/widget/TextInputLayout.java
+++ b/design/src/android/support/design/widget/TextInputLayout.java
@@ -93,6 +93,12 @@
  *
  * &lt;/android.support.design.widget.TextInputLayout&gt;
  * </pre>
+ *
+ * <p><strong>Note:</strong> The actual view hierarchy present under TextInputLayout is
+ * <strong>NOT</strong> guaranteed to match the view hierarchy as written in XML. As a result,
+ * calls to getParent() on children of the TextInputLayout -- such as an TextInputEditText --
+ * may not return the TextInputLayout itself, but rather an intermediate View. If you need
+ * to access a View directly, set an {@code android:id} and use {@link View#findViewById(int)}.
  */
 public class TextInputLayout extends LinearLayout {
 
diff --git a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java b/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
index f6350c1..9fff6a2 100644
--- a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
+++ b/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
@@ -31,7 +31,9 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.Instrumentation;
+import android.graphics.Rect;
 import android.support.design.testutils.CoordinatorLayoutUtils;
+import android.support.design.widget.CoordinatorLayout.Behavior;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SdkSuppress;
 import android.support.v4.view.ViewCompat;
@@ -39,7 +41,9 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.Gravity;
 import android.view.View;
+import android.view.View.MeasureSpec;
 
+import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
@@ -48,10 +52,17 @@
 @MediumTest
 public class CoordinatorLayoutTest extends BaseInstrumentationTestCase<CoordinatorLayoutActivity> {
 
+    private Instrumentation mInstrumentation;
+
     public CoordinatorLayoutTest() {
         super(CoordinatorLayoutActivity.class);
     }
 
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
     @Test
     @SdkSuppress(minSdkVersion = 21)
     public void testSetFitSystemWindows() {
@@ -334,4 +345,51 @@
         });
     }
 
+    @Test
+    public void testDodgeInsetBeforeLayout() throws Throwable {
+        final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout;
+
+        // Add a dummy view, which will be used to trigger a hierarchy change.
+        final View dummy = new View(col.getContext());
+
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                col.addView(dummy);
+            }
+        });
+
+        // Wait for a layout.
+        mInstrumentation.waitForIdleSync();
+
+        final View dodge = new View(col.getContext());
+        final CoordinatorLayout.LayoutParams lpDodge = col.generateDefaultLayoutParams();
+        lpDodge.dodgeInsetEdges = Gravity.BOTTOM;
+        lpDodge.setBehavior(new Behavior() {
+            @Override
+            public boolean getInsetDodgeRect(CoordinatorLayout parent, View child, Rect rect) {
+                // Any non-empty rect is fine here.
+                rect.set(0, 0, 10, 10);
+                return true;
+            }
+        });
+
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                col.addView(dodge, lpDodge);
+
+                // Ensure the new view is in the list of children.
+                int heightSpec = MeasureSpec.makeMeasureSpec(col.getHeight(), MeasureSpec.EXACTLY);
+                int widthSpec = MeasureSpec.makeMeasureSpec(col.getWidth(), MeasureSpec.EXACTLY);
+                col.measure(widthSpec, heightSpec);
+
+                // Force a hierarchy change.
+                col.removeView(dummy);
+            }
+        });
+
+        // Wait for a layout.
+        mInstrumentation.waitForIdleSync();
+    }
 }
diff --git a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
index 639e906..26a8444 100644
--- a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
@@ -42,6 +42,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -341,7 +342,11 @@
             return;
         }
         int eventType = parser.getEventType();
-        while (eventType != XmlPullParser.END_DOCUMENT) {
+        final int innerDepth = parser.getDepth() + 1;
+
+        // Parse everything until the end of the animated-vector element.
+        while (eventType != XmlPullParser.END_DOCUMENT
+                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
                 if (DBG_ANIMATION_VECTOR_DRAWABLE) {
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
index 7dc7b9f..57c8c93 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -14,11 +14,7 @@
 
 package android.support.graphics.drawable;
 
-import android.support.annotation.RestrictTo;
-import android.support.v4.content.res.ResourcesCompat;
-import android.support.v4.graphics.drawable.DrawableCompat;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
+import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
 
 import android.annotation.TargetApi;
 import android.content.res.ColorStateList;
@@ -38,34 +34,190 @@
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
-import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.VectorDrawable;
 import android.os.Build;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Stack;
 
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
-
 /**
  * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
  * For older API version, this class lets you create a drawable based on an XML vector graphic.
- * <p>
- * VectorDrawableCompat are defined in the same XML format as {@link VectorDrawable}.
- * </p>
+ * <p/>
  * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API.
  * In order to refer to VectorDrawableCompat inside a XML file,  you can use app:srcCompat attribute
  * in AppCompat library's ImageButton or ImageView.
+ * <p/>
+ * <strong>Note:</strong> To optimize for the re-drawing performance, one bitmap cache is created
+ * for each VectorDrawableCompat. Therefore, referring to the same VectorDrawableCompat means
+ * sharing the same bitmap cache. If these references don't agree upon on the same size, the bitmap
+ * will be recreated and redrawn every time size is changed. In other words, if a VectorDrawable is
+ * used for different sizes, it is more efficient to create multiple VectorDrawables, one for each
+ * size.
+ * <p/>
+ * VectorDrawableCompat can be defined in an XML file with the <code>&lt;vector></code> element.
+ * <p/>
+ * The VectorDrawableCompat has the following elements:
+ * <p/>
+ * <dt><code>&lt;vector></code></dt>
+ * <dl>
+ * <dd>Used to define a vector drawable
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of this vector drawable.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:width</code></dt>
+ * <dd>Used to define the intrinsic width of the drawable.
+ * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:height</code></dt>
+ * <dd>Used to define the intrinsic height the drawable.
+ * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:viewportWidth</code></dt>
+ * <dd>Used to define the width of the viewport space. Viewport is basically
+ * the virtual canvas where the paths are drawn on.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:viewportHeight</code></dt>
+ * <dd>Used to define the height of the viewport space. Viewport is basically
+ * the virtual canvas where the paths are drawn on.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:tint</code></dt>
+ * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:tintMode</code></dt>
+ * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:autoMirrored</code></dt>
+ * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
+ * RTL (right-to-left).</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:alpha</code></dt>
+ * <dd>The opacity of this drawable.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * </dl></dd>
+ * </dl>
+ *
+ * <dl>
+ * <dt><code>&lt;group></code></dt>
+ * <dd>Defines a group of paths or subgroups, plus transformation information.
+ * The transformations are defined in the same coordinates as the viewport.
+ * And the transformations are applied in the order of scale, rotate then translate.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the group.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:rotation</code></dt>
+ * <dd>The degrees of rotation of the group.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:pivotX</code></dt>
+ * <dd>The X coordinate of the pivot for the scale and rotation of the group.
+ * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:pivotY</code></dt>
+ * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
+ * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:scaleX</code></dt>
+ * <dd>The amount of scale on the X Coordinate.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:scaleY</code></dt>
+ * <dd>The amount of scale on the Y coordinate.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:translateX</code></dt>
+ * <dd>The amount of translation on the X coordinate.
+ * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:translateY</code></dt>
+ * <dd>The amount of translation on the Y coordinate.
+ * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * </dl></dd>
+ * </dl>
+ *
+ * <dl>
+ * <dt><code>&lt;path></code></dt>
+ * <dd>Defines paths to be drawn.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the path.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines path data using exactly same format as "d" attribute
+ * in the SVG's path data. This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:fillColor</code></dt>
+ * <dd>Specifies the color used to fill the path.
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path fill is drawn if this property is not specified.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:strokeColor</code></dt>
+ * <dd>Specifies the color used to draw the path outline.
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path outline is drawn if this property is not specified.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:strokeWidth</code></dt>
+ * <dd>The width a path stroke.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:strokeAlpha</code></dt>
+ * <dd>The opacity of a path stroke.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:fillAlpha</code></dt>
+ * <dd>The opacity to fill the path with.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:trimPathStart</code></dt>
+ * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:trimPathEnd</code></dt>
+ * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:trimPathOffset</code></dt>
+ * <dd>Shift trim region (allows showed region to include the start and end), in the range
+ * from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * <dt><code>android:strokeLineCap</code></dt>
+ * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:strokeLineJoin</code></dt>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:strokeMiterLimit</code></dt>
+ * <dd>Sets the Miter limit for a stroked path.</dd>
+ * <dd>Animatable : No.</dd>
+ * </dl></dd>
+ * </dl>
+ *
+ * <dl>
+ * <dt><code>&lt;clip-path></code></dt>
+ * <dd>Defines path to be the current clip. Note that the clip path only apply to
+ * the current group and its children.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the clip path.</dd>
+ * <dd>Animatable : No.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines clip path using the same format as "d" attribute
+ * in the SVG's path data.</dd>
+ * <dd>Animatable : Yes.</dd>
+ * </dl></dd>
+ * </dl>
  */
+
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public class VectorDrawableCompat extends VectorDrawableCommon {
     static final String LOGTAG = "VectorDrawableCompat";
@@ -585,7 +737,11 @@
         groupStack.push(pathRenderer.mRootGroup);
 
         int eventType = parser.getEventType();
-        while (eventType != XmlPullParser.END_DOCUMENT) {
+        final int innerDepth = parser.getDepth() + 1;
+
+        // Parse everything until the end of the vector element.
+        while (eventType != XmlPullParser.END_DOCUMENT
+                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
                 final VGroup currentGroup = groupStack.peek();
diff --git a/transition/Android.mk b/transition/Android.mk
index a401d77..254b758 100644
--- a/transition/Android.mk
+++ b/transition/Android.mk
@@ -43,6 +43,7 @@
 LOCAL_MODULE := android-support-transition-ics
 LOCAL_SDK_VERSION := 14
 LOCAL_SRC_FILES := $(call all-java-files-under, ics)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-transition-base
 LOCAL_JAVA_LIBRARIES := android-support-transition-res \
     android-support-v4
@@ -53,6 +54,7 @@
 LOCAL_MODULE := android-support-transition-kitkat
 LOCAL_SDK_VERSION := 19
 LOCAL_SRC_FILES := $(call all-java-files-under, kitkat)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-transition-ics
 LOCAL_JAVA_LIBRARIES := android-support-transition-res \
     android-support-v4
@@ -63,6 +65,7 @@
 LOCAL_MODULE := android-support-transition-api21
 LOCAL_SDK_VERSION := 21
 LOCAL_SRC_FILES := $(call all-java-files-under, api21)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-transition-kitkat
 LOCAL_JAVA_LIBRARIES := android-support-transition-res \
     android-support-v4
@@ -73,6 +76,7 @@
 LOCAL_MODULE := android-support-transition-api23
 LOCAL_SDK_VERSION := 23
 LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-transition-api21
 LOCAL_JAVA_LIBRARIES := android-support-transition-res \
     android-support-v4
@@ -86,6 +90,7 @@
 LOCAL_MODULE := android-support-transition
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-transition-api23
 LOCAL_JAVA_LIBRARIES := android-support-transition-res \
     android-support-v4
diff --git a/v17/leanback/res/values-bs-rBA/strings.xml b/v17/leanback/res/values-bs-rBA/strings.xml
index 63a76e2..cdfe434 100644
--- a/v17/leanback/res/values-bs-rBA/strings.xml
+++ b/v17/leanback/res/values-bs-rBA/strings.xml
@@ -53,5 +53,5 @@
     <string name="lb_date_separator" msgid="2440386660906697298">"/"</string>
     <string name="lb_time_separator" msgid="2763247350845477227">":"</string>
     <string name="lb_onboarding_get_started" msgid="6961440391306351139">"ZAPOČNITE"</string>
-    <string name="lb_onboarding_accessibility_next" msgid="2918313444257732434">"Naprijed"</string>
+    <string name="lb_onboarding_accessibility_next" msgid="2918313444257732434">"Sljedeća"</string>
 </resources>
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV9.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV9.java
index 4e25f71..a203252 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV9.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV9.java
@@ -304,6 +304,10 @@
 
     @Override
     public void onDestroy() {
+        if (mInvalidatePanelMenuPosted) {
+            mWindow.getDecorView().removeCallbacks(mInvalidatePanelMenuRunnable);
+        }
+
         super.onDestroy();
 
         if (mActionBar != null) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java b/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
index 6f42ea9..b51df4b 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
@@ -89,11 +89,10 @@
     private static void installDefaultInflateDelegates(@NonNull AppCompatDrawableManager manager) {
         final int sdk = Build.VERSION.SDK_INT;
         // This sdk version check will affect src:appCompat code path.
+        // Although VectorDrawable exists in Android framework from Lollipop, AppCompat will use the
+        // VectorDrawableCompat before Nougat to utilize the bug fixes in VectorDrawableCompat.
         if (sdk < 24) {
-            // We only want to use the automatic VectorDrawableCompat handling where it's
-            // needed: on devices running before Lollipop
             manager.addDelegate("vector", new VdcInflateDelegate());
-
             if (sdk >= 11) {
                 // AnimatedVectorDrawableCompat only works on API v11+
                 manager.addDelegate("animated-vector", new AvdcInflateDelegate());
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 95c6ac2..ab27c9e 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -2821,6 +2821,11 @@
                 final Object obj = msg.obj;
                 final int arg = msg.arg1;
 
+                if (what == MSG_ROUTE_CHANGED
+                        && getSelectedRoute().getId().equals(((RouteInfo) obj).getId())) {
+                    updateSelectedRouteIfNeeded(true);
+                }
+
                 // Synchronize state with the system media router.
                 syncWithSystemProvider(what, obj);
 
diff --git a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
index 6a2451b..a31eb6f 100644
--- a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
+++ b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
@@ -296,7 +296,6 @@
             if (mRouteTypes != newRouteTypes || mActiveScan != newActiveScan) {
                 mRouteTypes = newRouteTypes;
                 mActiveScan = newActiveScan;
-                updateCallback();
                 updateSystemRoutes();
             }
         }
@@ -309,6 +308,7 @@
         }
 
         private void updateSystemRoutes() {
+            updateCallback();
             boolean changed = false;
             for (Object routeObj : MediaRouterJellybean.getRoutes(mRouterObj)) {
                 changed |= addSystemRouteNoPublish(routeObj);
diff --git a/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java b/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
index 915556e..37197e4 100644
--- a/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
+++ b/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
@@ -53,6 +53,7 @@
                     }
                 }
 
+                @Override
                 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                     if (dx != 0 || dy != 0) {
                         mScrolled = true;
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
index 3a72152..9109c87 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseGridLayoutManagerTest.java
@@ -16,6 +16,7 @@
 package android.support.v7.widget;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -152,6 +153,8 @@
 
         CountDownLatch prefetchLatch;
 
+        OrientationHelper mSecondaryOrientation;
+
         List<GridLayoutManagerTest.Callback>
                 mCallbacks = new ArrayList<GridLayoutManagerTest.Callback>();
 
@@ -182,6 +185,26 @@
         }
 
         @Override
+        public void setOrientation(int orientation) {
+            super.setOrientation(orientation);
+            mSecondaryOrientation = null;
+        }
+
+        @Override
+        void ensureLayoutState() {
+            super.ensureLayoutState();
+            if (mSecondaryOrientation == null) {
+                if (getOrientation() == RecyclerView.HORIZONTAL) {
+                    mSecondaryOrientation = OrientationHelper.createOrientationHelper(this,
+                        RecyclerView.VERTICAL);
+                } else {
+                    mSecondaryOrientation = OrientationHelper.createOrientationHelper(this,
+                        RecyclerView.HORIZONTAL);
+                }
+            }
+        }
+
+        @Override
         public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
             try {
                 for (GridLayoutManagerTest.Callback callback : mCallbacks) {
@@ -213,6 +236,23 @@
             };
         }
 
+        Rect getViewBounds(View view) {
+            if (getOrientation() == HORIZONTAL) {
+                return new Rect(
+                    mOrientationHelper.getDecoratedStart(view),
+                    mSecondaryOrientation.getDecoratedStart(view),
+                    mOrientationHelper.getDecoratedEnd(view),
+                    mSecondaryOrientation.getDecoratedEnd(view));
+            } else {
+                return new Rect(
+                    mSecondaryOrientation.getDecoratedStart(view),
+                    mOrientationHelper.getDecoratedStart(view),
+                    mSecondaryOrientation.getDecoratedEnd(view),
+                    mOrientationHelper.getDecoratedEnd(view));
+            }
+
+        }
+
         public void expectLayout(int layoutCount) {
             mLayoutLatch = new CountDownLatch(layoutCount);
         }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseLinearLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseLinearLayoutManagerTest.java
index 50c9ba3..54190f1 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseLinearLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseLinearLayoutManagerTest.java
@@ -21,12 +21,14 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.support.annotation.Nullable;
 import android.support.v4.util.Pair;
 import android.util.Log;
 import android.view.View;
@@ -83,14 +85,21 @@
     }
 
     void setupByConfig(Config config, boolean waitForFirstLayout) throws Throwable {
+        setupByConfig(config, waitForFirstLayout, null, null);
+    }
+
+    void setupByConfig(Config config, boolean waitForFirstLayout,
+        @Nullable RecyclerView.LayoutParams childLayoutParams,
+        @Nullable RecyclerView.LayoutParams parentLayoutParams) throws Throwable {
         mRecyclerView = inflateWrappedRV();
 
         mRecyclerView.setHasFixedSize(true);
-        mTestAdapter = config.mTestAdapter == null ? new TestAdapter(config.mItemCount)
+        mTestAdapter = config.mTestAdapter == null
+                ? new TestAdapter(config.mItemCount, childLayoutParams)
                 : config.mTestAdapter;
         mRecyclerView.setAdapter(mTestAdapter);
         mLayoutManager = new WrappedLinearLayoutManager(getActivity(), config.mOrientation,
-                config.mReverseLayout);
+            config.mReverseLayout);
         mLayoutManager.setStackFromEnd(config.mStackFromEnd);
         mLayoutManager.setRecycleChildrenOnDetach(config.mRecycleChildrenOnDetach);
         mRecyclerView.setLayoutManager(mLayoutManager);
@@ -102,6 +111,10 @@
                     )
             );
         }
+        if (parentLayoutParams != null) {
+            mRecyclerView.setLayoutParams(parentLayoutParams);
+        }
+
         if (waitForFirstLayout) {
             waitForFirstLayout();
         }
@@ -342,15 +355,26 @@
     class WrappedLinearLayoutManager extends LinearLayoutManager {
 
         CountDownLatch layoutLatch;
-
         CountDownLatch snapLatch;
-
         CountDownLatch prefetchLatch;
+        CountDownLatch callbackLatch;
 
         OrientationHelper mSecondaryOrientation;
 
         OnLayoutListener mOnLayoutListener;
 
+        RecyclerView.OnScrollListener mCallbackListener = new RecyclerView.OnScrollListener() {
+
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                super.onScrollStateChanged(recyclerView, newState);
+                callbackLatch.countDown();
+                if (callbackLatch.getCount() == 0L) {
+                    removeOnScrollListener(this);
+                }
+            }
+        };
+
         public WrappedLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
             super(context, orientation, reverseLayout);
         }
@@ -359,6 +383,15 @@
             layoutLatch = new CountDownLatch(count);
         }
 
+        public void expectCallbacks(int count) throws Throwable {
+            callbackLatch = new CountDownLatch(count);
+            mRecyclerView.addOnScrollListener(mCallbackListener);
+        }
+
+        private void removeOnScrollListener(RecyclerView.OnScrollListener listener) {
+            mRecyclerView.removeOnScrollListener(listener);
+        }
+
         public void waitForLayout(int seconds) throws Throwable {
             layoutLatch.await(seconds * (DEBUG ? 100 : 1), SECONDS);
             checkForMainThreadException();
@@ -372,6 +405,13 @@
             });
         }
 
+        public void assertNoCallbacks(String msg, long timeout) throws Throwable {
+            callbackLatch.await(timeout, TimeUnit.SECONDS);
+            long latchCount = callbackLatch.getCount();
+            assertFalse(msg + " :" + latchCount, latchCount == 0);
+            removeOnScrollListener(mCallbackListener);
+        }
+
         public void expectPrefetch(int count) {
             prefetchLatch = new CountDownLatch(count);
         }
@@ -413,8 +453,7 @@
             // use a runnable to ensure RV layout is finished
             getInstrumentation().runOnMainSync(new Runnable() {
                 @Override
-                public void run() {
-                }
+                public void run() {}
             });
         }
 
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
index 7a7a4d4..0373251 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
@@ -27,6 +27,7 @@
 import android.app.Instrumentation;
 import android.graphics.Rect;
 import android.os.Looper;
+import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.v4.view.ViewCompat;
@@ -791,10 +792,16 @@
 
         ViewAttachDetachCounter mAttachmentCounter = new ViewAttachDetachCounter();
         List<Item> mItems;
+        final @Nullable RecyclerView.LayoutParams mLayoutParams;
 
         public TestAdapter(int count) {
+            this(count, null);
+        }
+
+        public TestAdapter(int count, @Nullable RecyclerView.LayoutParams layoutParams) {
             mItems = new ArrayList<Item>(count);
             addItems(0, count, DEFAULT_ITEM_PREFIX);
+            mLayoutParams = layoutParams;
         }
 
         private void addItems(int pos, int count, String prefix) {
@@ -848,6 +855,9 @@
             final Item item = mItems.get(position);
             ((TextView) (holder.itemView)).setText(item.mText + "(" + item.mId + ")");
             holder.mBoundItem = item;
+            if (mLayoutParams != null) {
+                holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(mLayoutParams));
+            }
         }
 
         public Item getItemAt(int position) {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerSnappingTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerSnappingTest.java
index 0ba8fed..6dc80bd 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerSnappingTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerSnappingTest.java
@@ -168,7 +168,11 @@
         mGlm.waitForLayout(2);
 
         View view = findCenterView(mGlm);
-        int scrollDistance = (getViewDimension(view) / 2) + 10;
+        int scrollDistance = distFromCenter(view) / 2;
+        if (scrollDistance == 0) {
+            return;
+        }
+
         int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance;
 
         mGlm.expectIdleState(2);
@@ -208,6 +212,14 @@
         }
     }
 
+    private int distFromCenter(View view) {
+        if (mGlm.canScrollHorizontally()) {
+            return Math.abs(mRecyclerView.getWidth() / 2 - mGlm.getViewBounds(view).centerX());
+        } else {
+            return Math.abs(mRecyclerView.getHeight() / 2 - mGlm.getViewBounds(view).centerY());
+        }
+    }
+
     private boolean fling(final int velocityX, final int velocityY)
             throws Throwable {
         final AtomicBoolean didStart = new AtomicBoolean(false);
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerSnappingTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerSnappingTest.java
index ae19fc1..3d978da 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerSnappingTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerSnappingTest.java
@@ -59,6 +59,32 @@
 
     @MediumTest
     @Test
+    public void snapOnScrollSameViewEdge() throws Throwable {
+        final Config config = (Config) mConfig.clone();
+        // Ensure that the views are big enough to reach the pathological case when the view closest
+        // to the center is an edge view, but it cannot scroll further in order to snap.
+        setupByConfig(config, true, new RecyclerView.LayoutParams(1000, 1000),
+            new RecyclerView.LayoutParams(1500, 1500));
+        SnapHelper snapHelper = new LinearSnapHelper();
+        mLayoutManager.expectIdleState(1);
+        snapHelper.attachToRecyclerView(mRecyclerView);
+        mLayoutManager.waitForSnap(10);
+
+        // Record the current center view.
+        View view = findCenterView(mLayoutManager);
+
+        int scrollDistance = (getViewDimension(view) / 2) - 1;
+        int scrollDist = config.mStackFromEnd == config.mReverseLayout
+            ? -scrollDistance : scrollDistance;
+        mLayoutManager.expectIdleState(1);
+        smoothScrollBy(scrollDist);
+        mLayoutManager.waitForSnap(10);
+        mLayoutManager.expectCallbacks(5);
+        mLayoutManager.assertNoCallbacks("There should be no callbacks after some time", 3);
+    }
+
+    @MediumTest
+    @Test
     public void snapOnScrollSameView() throws Throwable {
         final Config config = (Config) mConfig.clone();
         setupByConfig(config, true);
@@ -76,7 +102,7 @@
 
         // Views have not changed
         View viewAfterFling = findCenterView(mLayoutManager);
-        assertSame("The view should have scrolled", view, viewAfterFling);
+        assertSame("The view should NOT have scrolled", view, viewAfterFling);
         assertCenterAligned(viewAfterFling);
     }
 
@@ -165,7 +191,11 @@
         mLayoutManager.waitForLayout(2);
 
         View view = findCenterView(mLayoutManager);
-        int scrollDistance = (getViewDimension(view) / 2) + 10;
+        int scrollDistance = distFromCenter(view) / 2;
+        if (scrollDistance == 0) {
+            return;
+        }
+
         int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance;
 
         mLayoutManager.expectIdleState(2);
@@ -201,6 +231,16 @@
         }
     }
 
+    private int distFromCenter(View view) {
+        if (mLayoutManager.canScrollHorizontally()) {
+            return Math.abs(mRecyclerView.getWidth() / 2 -
+                mLayoutManager.getViewBounds(view).centerX());
+        } else {
+            return Math.abs(mRecyclerView.getHeight() / 2 -
+                mLayoutManager.getViewBounds(view).centerY());
+        }
+    }
+
     private boolean fling(final int velocityX, final int velocityY) throws Throwable {
         final AtomicBoolean didStart = new AtomicBoolean(false);
         runTestOnUiThread(new Runnable() {