Merge "Provide compat API for MediaBrowser.search for API 26+"
diff --git a/api/25.3.0.txt b/api/25.3.0.txt
index 917fd00..ac4bf65 100644
--- a/api/25.3.0.txt
+++ b/api/25.3.0.txt
@@ -135,7 +135,9 @@
   public class CustomTabsCallback {
     ctor public CustomTabsCallback();
     method public void extraCallback(java.lang.String, android.os.Bundle);
+    method public void onMessageChannelReady(android.os.Bundle);
     method public void onNavigationEvent(int, android.os.Bundle);
+    method public void onPostMessage(java.lang.String, android.os.Bundle);
     field public static final int NAVIGATION_ABORTED = 4; // 0x4
     field public static final int NAVIGATION_FAILED = 3; // 0x3
     field public static final int NAVIGATION_FINISHED = 2; // 0x2
@@ -215,10 +217,19 @@
     method protected abstract boolean mayLaunchUrl(android.support.customtabs.CustomTabsSessionToken, android.net.Uri, android.os.Bundle, java.util.List<android.os.Bundle>);
     method protected abstract boolean newSession(android.support.customtabs.CustomTabsSessionToken);
     method public android.os.IBinder onBind(android.content.Intent);
+    method protected abstract int postMessage(android.support.customtabs.CustomTabsSessionToken, java.lang.String, android.os.Bundle);
+    method protected abstract boolean requestPostMessageChannel(android.support.customtabs.CustomTabsSessionToken, android.net.Uri);
     method protected abstract boolean updateVisuals(android.support.customtabs.CustomTabsSessionToken, android.os.Bundle);
     method protected abstract boolean warmup(long);
     field public static final java.lang.String ACTION_CUSTOM_TABS_CONNECTION = "android.support.customtabs.action.CustomTabsService";
     field public static final java.lang.String KEY_URL = "android.support.customtabs.otherurls.URL";
+    field public static final int RESULT_FAILURE_DISALLOWED = -1; // 0xffffffff
+    field public static final int RESULT_FAILURE_MESSAGING_ERROR = -3; // 0xfffffffd
+    field public static final int RESULT_FAILURE_REMOTE_ERROR = -2; // 0xfffffffe
+    field public static final int RESULT_SUCCESS = 0; // 0x0
+  }
+
+  public static abstract class CustomTabsService.Result implements java.lang.annotation.Annotation {
   }
 
   public abstract class CustomTabsServiceConnection implements android.content.ServiceConnection {
@@ -229,6 +240,8 @@
 
   public final class CustomTabsSession {
     method public boolean mayLaunchUrl(android.net.Uri, android.os.Bundle, java.util.List<android.os.Bundle>);
+    method public int postMessage(java.lang.String, android.os.Bundle);
+    method public boolean requestPostMessageChannel(android.net.Uri);
     method public boolean setActionButton(android.graphics.Bitmap, java.lang.String);
     method public boolean setSecondaryToolbarViews(android.widget.RemoteViews, int[], android.app.PendingIntent);
     method public deprecated boolean setToolbarItem(int, android.graphics.Bitmap, java.lang.String);
@@ -237,6 +250,24 @@
   public class CustomTabsSessionToken {
     method public android.support.customtabs.CustomTabsCallback getCallback();
     method public static android.support.customtabs.CustomTabsSessionToken getSessionTokenFromIntent(android.content.Intent);
+    method public boolean isAssociatedWith(android.support.customtabs.CustomTabsSession);
+  }
+
+  public class PostMessageService extends android.app.Service {
+    ctor public PostMessageService();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+  public abstract class PostMessageServiceConnection implements android.content.ServiceConnection {
+    ctor public PostMessageServiceConnection(android.support.customtabs.CustomTabsSessionToken);
+    method public boolean bindSessionToPostMessageService(android.content.Context, java.lang.String);
+    method public final boolean notifyMessageChannelReady(android.os.Bundle);
+    method public void onPostMessageServiceConnected();
+    method public void onPostMessageServiceDisconnected();
+    method public final void onServiceConnected(android.content.ComponentName, android.os.IBinder);
+    method public final void onServiceDisconnected(android.content.ComponentName);
+    method public final boolean postMessage(java.lang.String, android.os.Bundle);
+    method public void unbindFromContext(android.content.Context);
   }
 
 }
@@ -874,7 +905,8 @@
     method public java.lang.String getAttribute(java.lang.String);
     method public double getAttributeDouble(java.lang.String, double);
     method public int getAttributeInt(java.lang.String, int);
-    method public boolean getLatLong(float[]);
+    method public deprecated boolean getLatLong(float[]);
+    method public double[] getLatLong();
     method public byte[] getThumbnail();
     method public android.graphics.Bitmap getThumbnailBitmap();
     method public byte[] getThumbnailBytes();
@@ -883,6 +915,7 @@
     method public boolean isThumbnailCompressed();
     method public void saveAttributes() throws java.io.IOException;
     method public void setAttribute(java.lang.String, java.lang.String);
+    method public void setLatLong(double, double);
     field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
     field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
     field public static final int ORIENTATION_NORMAL = 1; // 0x1
@@ -1521,6 +1554,7 @@
     method public final boolean isHeadersTransitionOnBackEnabled();
     method public boolean isInHeadersTransition();
     method public boolean isShowingHeaders();
+    method public android.support.v17.leanback.app.HeadersFragment onCreateHeadersFragment();
     method protected void onEntranceTransitionEnd();
     method protected void onEntranceTransitionPrepare();
     method protected void onEntranceTransitionStart();
@@ -1625,6 +1659,7 @@
     method public final boolean isHeadersTransitionOnBackEnabled();
     method public boolean isInHeadersTransition();
     method public boolean isShowingHeaders();
+    method public android.support.v17.leanback.app.HeadersSupportFragment onCreateHeadersSupportFragment();
     method protected void onEntranceTransitionEnd();
     method protected void onEntranceTransitionPrepare();
     method protected void onEntranceTransitionStart();
@@ -2259,6 +2294,7 @@
     method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
     method public android.graphics.drawable.Drawable getBadgeDrawable();
     method public android.content.Intent getRecognizerIntent();
+    method public android.support.v17.leanback.app.RowsFragment getRowsFragment();
     method public java.lang.String getTitle();
     method public static android.support.v17.leanback.app.SearchFragment newInstance(java.lang.String);
     method public void setBadgeDrawable(android.graphics.drawable.Drawable);
@@ -2288,6 +2324,7 @@
     method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
     method public android.graphics.drawable.Drawable getBadgeDrawable();
     method public android.content.Intent getRecognizerIntent();
+    method public android.support.v17.leanback.app.RowsSupportFragment getRowsSupportFragment();
     method public java.lang.String getTitle();
     method public static android.support.v17.leanback.app.SearchSupportFragment newInstance(java.lang.String);
     method public void setBadgeDrawable(android.graphics.drawable.Drawable);
@@ -2575,6 +2612,7 @@
 
   public static abstract class PlaybackGlueHost.HostCallback {
     ctor public PlaybackGlueHost.HostCallback();
+    method public void onHostDestroy();
     method public void onHostPause();
     method public void onHostResume();
     method public void onHostStart();
@@ -2902,6 +2940,7 @@
     ctor public FocusHighlightHelper();
     method public static void setupBrowseItemFocusHighlight(android.support.v17.leanback.widget.ItemBridgeAdapter, int, boolean);
     method public static void setupHeaderItemFocusHighlight(android.support.v17.leanback.widget.VerticalGridView);
+    method public static void setupHeaderItemFocusHighlight(android.support.v17.leanback.widget.VerticalGridView, boolean);
   }
 
   public abstract interface FragmentAnimationProvider {
@@ -3303,6 +3342,7 @@
     method public final void onViewRecycled(android.support.v7.widget.RecyclerView.ViewHolder);
     method public void setAdapter(android.support.v17.leanback.widget.ObjectAdapter);
     method public void setAdapterListener(android.support.v17.leanback.widget.ItemBridgeAdapter.AdapterListener);
+    method public void setPresenter(android.support.v17.leanback.widget.PresenterSelector);
     method public void setPresenterMapper(java.util.ArrayList<android.support.v17.leanback.widget.Presenter>);
     method public void setWrapper(android.support.v17.leanback.widget.ItemBridgeAdapter.Wrapper);
   }
@@ -4228,6 +4268,18 @@
     method public void setStaticLabels(java.lang.CharSequence[]);
   }
 
+  public class TimePicker extends android.support.v17.leanback.widget.picker.Picker {
+    ctor public TimePicker(android.content.Context, android.util.AttributeSet);
+    ctor public TimePicker(android.content.Context, android.util.AttributeSet, int);
+    method public int getHour();
+    method public int getMinute();
+    method public boolean is24Hour();
+    method public boolean isPm();
+    method public void setHour(int);
+    method public void setIs24Hour(boolean);
+    method public void setMinute(int);
+  }
+
 }
 
 package android.support.v17.preference {
@@ -5651,6 +5703,7 @@
     method public android.content.ComponentName getServiceComponent();
     method public android.support.v4.media.session.MediaSessionCompat.Token getSessionToken();
     method public boolean isConnected();
+    method public void search(java.lang.String, android.os.Bundle, android.support.v4.media.MediaBrowserCompat.SearchCallback);
     method public void subscribe(java.lang.String, android.support.v4.media.MediaBrowserCompat.SubscriptionCallback);
     method public void subscribe(java.lang.String, android.os.Bundle, android.support.v4.media.MediaBrowserCompat.SubscriptionCallback);
     method public void unsubscribe(java.lang.String);
@@ -5688,6 +5741,12 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
+  public static abstract class MediaBrowserCompat.SearchCallback {
+    ctor public MediaBrowserCompat.SearchCallback();
+    method public void onError(java.lang.String, android.os.Bundle);
+    method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>);
+  }
+
   public static abstract class MediaBrowserCompat.SubscriptionCallback {
     ctor public MediaBrowserCompat.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>);
@@ -5708,6 +5767,7 @@
     method public abstract void onLoadChildren(java.lang.String, android.support.v4.media.MediaBrowserServiceCompat.Result<java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>>);
     method public void onLoadChildren(java.lang.String, android.support.v4.media.MediaBrowserServiceCompat.Result<java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>>, android.os.Bundle);
     method public void onLoadItem(java.lang.String, android.support.v4.media.MediaBrowserServiceCompat.Result<android.support.v4.media.MediaBrowserCompat.MediaItem>);
+    method public void onSearch(java.lang.String, android.os.Bundle, android.support.v4.media.MediaBrowserServiceCompat.Result<java.util.List<android.support.v4.media.MediaBrowserCompat.MediaItem>>);
     method public void setSessionToken(android.support.v4.media.session.MediaSessionCompat.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -5719,7 +5779,7 @@
     field public static final java.lang.String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
     field public static final java.lang.String EXTRA_RECENT = "android.service.media.extra.RECENT";
     field public static final java.lang.String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
-    field public static final java.lang.String EXTRA_SUGGESTION_KEYWORDS = "android.service.media.extra.SUGGESTION_KEYWORDS";
+    field public static final deprecated java.lang.String EXTRA_SUGGESTION_KEYWORDS = "android.service.media.extra.SUGGESTION_KEYWORDS";
   }
 
   public static class MediaBrowserServiceCompat.Result<T> {
@@ -5780,6 +5840,7 @@
     method public int size();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.support.v4.media.MediaMetadataCompat> CREATOR;
+    field public static final java.lang.String METADATA_KEY_ADVERTISEMENT = "android.media.metadata.ADVERTISEMENT";
     field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
     field public static final java.lang.String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
     field public static final java.lang.String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
@@ -5964,9 +6025,11 @@
     method public java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
+    method public int getRepeatMode();
     method public android.app.PendingIntent getSessionActivity();
     method public android.support.v4.media.session.MediaSessionCompat.Token getSessionToken();
     method public android.support.v4.media.session.MediaControllerCompat.TransportControls getTransportControls();
+    method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.support.v4.media.session.MediaControllerCompat.Callback);
     method public void registerCallback(android.support.v4.media.session.MediaControllerCompat.Callback, android.os.Handler);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
@@ -5984,8 +6047,10 @@
     method public void onPlaybackStateChanged(android.support.v4.media.session.PlaybackStateCompat);
     method public void onQueueChanged(java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
+    method public void onRepeatModeChanged(int);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
+    method public void onShuffleModeChanged(boolean);
   }
 
   public static final class MediaControllerCompat.PlaybackInfo {
@@ -6014,6 +6079,8 @@
     method public abstract void sendCustomAction(android.support.v4.media.session.PlaybackStateCompat.CustomAction, android.os.Bundle);
     method public abstract void sendCustomAction(java.lang.String, android.os.Bundle);
     method public abstract void setRating(android.support.v4.media.RatingCompat);
+    method public abstract void setRepeatMode(int);
+    method public abstract void setShuffleModeEnabled(boolean);
     method public abstract void skipToNext();
     method public abstract void skipToPrevious();
     method public abstract void skipToQueueItem(long);
@@ -6047,7 +6114,9 @@
     method public void setQueue(java.util.List<android.support.v4.media.session.MediaSessionCompat.QueueItem>);
     method public void setQueueTitle(java.lang.CharSequence);
     method public void setRatingType(int);
+    method public void setRepeatMode(int);
     method public void setSessionActivity(android.app.PendingIntent);
+    method public void setShuffleModeEnabled(boolean);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
@@ -6070,6 +6139,8 @@
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.support.v4.media.RatingCompat);
+    method public void onSetRepeatMode(int);
+    method public void onSetShuffleModeEnabled(boolean);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
     method public void onSkipToQueueItem(long);
@@ -6122,6 +6193,7 @@
     method public long getActiveQueueItemId();
     method public long getBufferedPosition();
     method public java.util.List<android.support.v4.media.session.PlaybackStateCompat.CustomAction> getCustomActions();
+    method public int getErrorCode();
     method public java.lang.CharSequence getErrorMessage();
     method public android.os.Bundle getExtras();
     method public long getLastPositionUpdateTime();
@@ -6145,12 +6217,29 @@
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
+    field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L
+    field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.support.v4.media.session.PlaybackStateCompat> CREATOR;
+    field public static final int ERROR_CODE_ACTION_ABORTED = 10; // 0xa
+    field public static final int ERROR_CODE_APP_ERROR = 1; // 0x1
+    field public static final int ERROR_CODE_AUTHENTICATION_EXPIRED = 3; // 0x3
+    field public static final int ERROR_CODE_CONCURRENT_STREAM_LIMIT = 5; // 0x5
+    field public static final int ERROR_CODE_CONTENT_ALREADY_PLAYING = 8; // 0x8
+    field public static final int ERROR_CODE_END_OF_QUEUE = 11; // 0xb
+    field public static final int ERROR_CODE_NOT_AVAILABLE_IN_REGION = 7; // 0x7
+    field public static final int ERROR_CODE_NOT_SUPPORTED = 2; // 0x2
+    field public static final int ERROR_CODE_PARENTAL_CONTROL_RESTRICTED = 6; // 0x6
+    field public static final int ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED = 4; // 0x4
+    field public static final int ERROR_CODE_SKIP_LIMIT_REACHED = 9; // 0x9
+    field public static final int ERROR_CODE_UNKNOWN_ERROR = 0; // 0x0
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
+    field public static final int REPEAT_MODE_ALL = 2; // 0x2
+    field public static final int REPEAT_MODE_NONE = 0; // 0x0
+    field public static final int REPEAT_MODE_ONE = 1; // 0x1
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
     field public static final int STATE_ERROR = 7; // 0x7
@@ -6174,7 +6263,8 @@
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setActions(long);
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setActiveQueueItemId(long);
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setBufferedPosition(long);
-    method public android.support.v4.media.session.PlaybackStateCompat.Builder setErrorMessage(java.lang.CharSequence);
+    method public deprecated android.support.v4.media.session.PlaybackStateCompat.Builder setErrorMessage(java.lang.CharSequence);
+    method public android.support.v4.media.session.PlaybackStateCompat.Builder setErrorMessage(int, java.lang.CharSequence);
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setExtras(android.os.Bundle);
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setState(int, long, float);
     method public android.support.v4.media.session.PlaybackStateCompat.Builder setState(int, long, float, long);
@@ -10038,7 +10128,8 @@
     method public int findLastVisibleItemPosition();
     method public android.support.v7.widget.RecyclerView.LayoutParams generateDefaultLayoutParams();
     method protected int getExtraLayoutSpace(android.support.v7.widget.RecyclerView.State);
-    method public int getInitialItemPrefetchCount();
+    method public deprecated int getInitialItemPrefetchCount();
+    method public int getInitialPrefetchItemCount();
     method public int getOrientation();
     method public boolean getRecycleChildrenOnDetach();
     method public boolean getReverseLayout();
@@ -10504,6 +10595,7 @@
     method public boolean isLayoutHierarchical(android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
     method public boolean isMeasurementCacheEnabled();
     method public boolean isSmoothScrolling();
+    method public boolean isViewPartiallyVisible(android.view.View, boolean, boolean);
     method public void layoutDecorated(android.view.View, int, int, int, int);
     method public void layoutDecoratedWithMargins(android.view.View, int, int, int, int);
     method public void measureChild(android.view.View, int, int);
@@ -10548,6 +10640,7 @@
     method public void removeView(android.view.View);
     method public void removeViewAt(int);
     method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean);
+    method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean, boolean);
     method public void requestLayout();
     method public void requestSimpleAnimationsInNextLayout();
     method public int scrollHorizontallyBy(int, android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
diff --git a/api/26.0.0.txt b/api/26.0.0.txt
index 07a1885..3d77c5b 100644
--- a/api/26.0.0.txt
+++ b/api/26.0.0.txt
@@ -4828,18 +4828,18 @@
     method public static java.lang.String capabilityToString(int);
     method public static java.lang.String feedbackTypeToString(int);
     method public static java.lang.String flagToString(int);
-    method public static boolean getCanRetrieveWindowContent(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static deprecated boolean getCanRetrieveWindowContent(android.accessibilityservice.AccessibilityServiceInfo);
     method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
     method public static deprecated java.lang.String getDescription(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static java.lang.String getId(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static android.content.pm.ResolveInfo getResolveInfo(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static java.lang.String getSettingsActivityName(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static deprecated java.lang.String getId(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static deprecated android.content.pm.ResolveInfo getResolveInfo(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static deprecated java.lang.String getSettingsActivityName(android.accessibilityservice.AccessibilityServiceInfo);
     method public static java.lang.String loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
     field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
     field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
     field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
-    field public static final int DEFAULT = 1; // 0x1
+    field public static final deprecated int DEFAULT = 1; // 0x1
     field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
     field public static final int FEEDBACK_BRAILLE = 32; // 0x20
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
@@ -5190,6 +5190,7 @@
     method public abstract android.support.v4.app.Fragment getFragment(android.os.Bundle, java.lang.String);
     method public abstract android.support.v4.app.Fragment getPrimaryNavigationFragment();
     method public abstract boolean isDestroyed();
+    method public abstract boolean isStateSaved();
     method public abstract void popBackStack();
     method public abstract void popBackStack(java.lang.String, int);
     method public abstract void popBackStack(int, int);
@@ -6222,8 +6223,7 @@
 package android.support.v4.math {
 
   public class MathUtils {
-    ctor public MathUtils();
-    method public static float clamp(float, int, int);
+    method public static float clamp(float, float, float);
     method public static double clamp(double, double, double);
     method public static int clamp(int, int, int);
   }
@@ -6898,11 +6898,11 @@
     ctor public OperationCanceledException(java.lang.String);
   }
 
-  public final class ParcelableCompat {
-    method public static <T> android.os.Parcelable.Creator<T> newCreator(android.support.v4.os.ParcelableCompatCreatorCallbacks<T>);
+  public final deprecated class ParcelableCompat {
+    method public static deprecated <T> android.os.Parcelable.Creator<T> newCreator(android.support.v4.os.ParcelableCompatCreatorCallbacks<T>);
   }
 
-  public abstract interface ParcelableCompatCreatorCallbacks<T> {
+  public abstract deprecated interface ParcelableCompatCreatorCallbacks<T> {
     method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader);
     method public abstract T[] newArray(int);
   }
diff --git a/api/current.txt b/api/current.txt
index 4285daf..8d12577 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -941,16 +941,34 @@
 
 package android.support.graphics.drawable {
 
-  public class AnimatedVectorDrawableCompat extends android.support.graphics.drawable.VectorDrawableCommon {
+  public abstract interface Animatable2Compat {
+    method public abstract void clearAnimationCallbacks();
+    method public abstract void registerAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
+    method public abstract boolean unregisterAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
+  }
+
+  public static abstract class Animatable2Compat.AnimationCallback {
+    ctor public Animatable2Compat.AnimationCallback();
+    method public void onAnimationEnd(android.graphics.drawable.Drawable);
+    method public void onAnimationStart(android.graphics.drawable.Drawable);
+  }
+
+  public class AnimatedVectorDrawableCompat extends android.support.graphics.drawable.VectorDrawableCommon implements android.support.graphics.drawable.Animatable2Compat {
+    method public void clearAnimationCallbacks();
+    method public static void clearAnimationCallbacks(android.graphics.drawable.Drawable);
     method public static android.support.graphics.drawable.AnimatedVectorDrawableCompat create(android.content.Context, int);
     method public static android.support.graphics.drawable.AnimatedVectorDrawableCompat createFromXmlInner(android.content.Context, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void draw(android.graphics.Canvas);
     method public int getOpacity();
     method public boolean isRunning();
+    method public void registerAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
+    method public static void registerAnimationCallback(android.graphics.drawable.Drawable, android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
     method public void setAlpha(int);
     method public void setColorFilter(android.graphics.ColorFilter);
     method public void start();
     method public void stop();
+    method public boolean unregisterAnimationCallback(android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
+    method public static boolean unregisterAnimationCallback(android.graphics.drawable.Drawable, android.support.graphics.drawable.Animatable2Compat.AnimationCallback);
   }
 
    abstract class VectorDrawableCommon extends android.graphics.drawable.Drawable {
@@ -1661,12 +1679,25 @@
 
 package android.support.transition {
 
+  public class ArcMotion extends android.support.transition.PathMotion {
+    ctor public ArcMotion();
+    method public float getMaximumAngle();
+    method public float getMinimumHorizontalAngle();
+    method public float getMinimumVerticalAngle();
+    method public android.graphics.Path getPath(float, float, float, float);
+    method public void setMaximumAngle(float);
+    method public void setMinimumHorizontalAngle(float);
+    method public void setMinimumVerticalAngle(float);
+  }
+
   public class AutoTransition extends android.support.transition.TransitionSet {
     ctor public AutoTransition();
+    ctor public AutoTransition(android.content.Context, android.util.AttributeSet);
   }
 
   public class ChangeBounds extends android.support.transition.Transition {
     ctor public ChangeBounds();
+    ctor public ChangeBounds(android.content.Context, android.util.AttributeSet);
     method public void captureEndValues(android.support.transition.TransitionValues);
     method public void captureStartValues(android.support.transition.TransitionValues);
     method public void setResizeClip(boolean);
@@ -1675,10 +1706,24 @@
   public class Fade extends android.support.transition.Visibility {
     ctor public Fade(int);
     ctor public Fade();
+    ctor public Fade(android.content.Context, android.util.AttributeSet);
     field public static final int IN = 1; // 0x1
     field public static final int OUT = 2; // 0x2
   }
 
+  public abstract class PathMotion {
+    ctor public PathMotion();
+    method public abstract android.graphics.Path getPath(float, float, float, float);
+  }
+
+  public class PatternPathMotion extends android.support.transition.PathMotion {
+    ctor public PatternPathMotion();
+    ctor public PatternPathMotion(android.graphics.Path);
+    method public android.graphics.Path getPath(float, float, float, float);
+    method public android.graphics.Path getPatternPath();
+    method public void setPatternPath(android.graphics.Path);
+  }
+
   public class Scene {
     ctor public Scene(android.view.ViewGroup);
     ctor public Scene(android.view.ViewGroup, android.view.View);
@@ -1692,6 +1737,7 @@
 
   public abstract class Transition {
     ctor public Transition();
+    ctor public Transition(android.content.Context, android.util.AttributeSet);
     method public android.support.transition.Transition addListener(android.support.transition.Transition.TransitionListener);
     method public android.support.transition.Transition addTarget(android.view.View);
     method public android.support.transition.Transition addTarget(int);
@@ -1711,6 +1757,7 @@
     method public long getDuration();
     method public android.animation.TimeInterpolator getInterpolator();
     method public java.lang.String getName();
+    method public android.support.transition.PathMotion getPathMotion();
     method public long getStartDelay();
     method public java.util.List<java.lang.Integer> getTargetIds();
     method public java.util.List<java.lang.String> getTargetNames();
@@ -1726,6 +1773,7 @@
     method public android.support.transition.Transition setDuration(long);
     method public android.support.transition.Transition setInterpolator(android.animation.TimeInterpolator);
     method public void setMatchOrder(int...);
+    method public void setPathMotion(android.support.transition.PathMotion);
     method public android.support.transition.Transition setStartDelay(long);
     field public static final int MATCH_ID = 3; // 0x3
     field public static final int MATCH_INSTANCE = 1; // 0x1
@@ -1741,6 +1789,12 @@
     method public abstract void onTransitionStart(android.support.transition.Transition);
   }
 
+  public class TransitionInflater {
+    method public static android.support.transition.TransitionInflater from(android.content.Context);
+    method public android.support.transition.Transition inflateTransition(int);
+    method public android.support.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
+  }
+
   public class TransitionManager {
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
@@ -1754,6 +1808,7 @@
 
   public class TransitionSet extends android.support.transition.Transition {
     ctor public TransitionSet();
+    ctor public TransitionSet(android.content.Context, android.util.AttributeSet);
     method public android.support.transition.TransitionSet addTransition(android.support.transition.Transition);
     method public void captureEndValues(android.support.transition.TransitionValues);
     method public void captureStartValues(android.support.transition.TransitionValues);
@@ -1774,11 +1829,18 @@
 
   public abstract class Visibility extends android.support.transition.Transition {
     ctor public Visibility();
+    ctor public Visibility(android.content.Context, android.util.AttributeSet);
     method public void captureEndValues(android.support.transition.TransitionValues);
     method public void captureStartValues(android.support.transition.TransitionValues);
+    method public int getMode();
     method public boolean isVisible(android.support.transition.TransitionValues);
     method public android.animation.Animator onAppear(android.view.ViewGroup, android.support.transition.TransitionValues, int, android.support.transition.TransitionValues, int);
+    method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.support.transition.TransitionValues, android.support.transition.TransitionValues);
     method public android.animation.Animator onDisappear(android.view.ViewGroup, android.support.transition.TransitionValues, int, android.support.transition.TransitionValues, int);
+    method public android.animation.Animator onDisappear(android.view.ViewGroup, android.view.View, android.support.transition.TransitionValues, android.support.transition.TransitionValues);
+    method public void setMode(int);
+    field public static final int MODE_IN = 1; // 0x1
+    field public static final int MODE_OUT = 2; // 0x2
   }
 
 }
@@ -6295,8 +6357,7 @@
 package android.support.v4.math {
 
   public class MathUtils {
-    ctor public MathUtils();
-    method public static float clamp(float, int, int);
+    method public static float clamp(float, float, float);
     method public static double clamp(double, double, double);
     method public static int clamp(int, int, int);
   }
@@ -9096,6 +9157,7 @@
     method public android.support.v7.graphics.drawable.DrawerArrowDrawable getDrawerArrowDrawable();
     method public android.view.View.OnClickListener getToolbarNavigationClickListener();
     method public boolean isDrawerIndicatorEnabled();
+    method public boolean isDrawerSlideAnimationEnabled();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onDrawerClosed(android.view.View);
     method public void onDrawerOpened(android.view.View);
@@ -9104,6 +9166,7 @@
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void setDrawerArrowDrawable(android.support.v7.graphics.drawable.DrawerArrowDrawable);
     method public void setDrawerIndicatorEnabled(boolean);
+    method public void setDrawerSlideAnimationEnabled(boolean);
     method public void setHomeAsUpIndicator(android.graphics.drawable.Drawable);
     method public void setHomeAsUpIndicator(int);
     method public void setToolbarNavigationClickListener(android.view.View.OnClickListener);
@@ -10762,7 +10825,8 @@
     method public int findLastVisibleItemPosition();
     method public android.support.v7.widget.RecyclerView.LayoutParams generateDefaultLayoutParams();
     method protected int getExtraLayoutSpace(android.support.v7.widget.RecyclerView.State);
-    method public int getInitialItemPrefetchCount();
+    method public deprecated int getInitialItemPrefetchCount();
+    method public int getInitialPrefetchItemCount();
     method public int getOrientation();
     method public boolean getRecycleChildrenOnDetach();
     method public boolean getReverseLayout();
diff --git a/buildSrc/dependencies.gradle b/buildSrc/dependencies.gradle
index 92eaf51..284fe01 100644
--- a/buildSrc/dependencies.gradle
+++ b/buildSrc/dependencies.gradle
@@ -26,7 +26,7 @@
 libs.espresso_contrib = 'com.android.support.test.espresso:espresso-contrib:2.3-alpha'
 
 // Keep gradle plugin version in sync with ub_supportlib-master manifest.
-libs.gradle = 'com.android.tools.build:gradle:2.2.4'
+libs.gradle = 'com.android.tools.build:gradle:2.3.0'
 
 // Other dependencies
 libs.xml_parser_apis = 'xerces:xmlParserAPIs:2.6.2'
diff --git a/buildSrc/diff_and_docs.gradle b/buildSrc/diff_and_docs.gradle
index 1e0e289..c6dda4f 100644
--- a/buildSrc/diff_and_docs.gradle
+++ b/buildSrc/diff_and_docs.gradle
@@ -38,7 +38,16 @@
     def hdfOption = new DoclavaMultilineJavadocOptionFileOption('hdf')
     hdfOption.add(
             ['android.whichdoc', 'online'],
-            ['android.hasSamples', 'true']);
+            ['android.hasSamples', 'true'])
+
+    // Track API change history.
+    def apiFilePattern = /(\d+\.\d+\.\d).txt/
+    def sinceOption = new DoclavaMultilineJavadocOptionFileOption('since')
+    File apiDir = new File(supportRootFolder, 'api')
+    apiDir.eachFileMatch FileType.FILES, ~apiFilePattern, { File apiFile ->
+        def apiLevel = (apiFile.name =~ apiFilePattern)[0][1]
+        sinceOption.add([apiFile.absolutePath, apiLevel])
+    }
 
     // Default hidden errors + hidden superclass (111) and
     // deprecation mismatch (113) to match framework docs.
@@ -55,6 +64,7 @@
         addStringOption "stubpackages", "android.support.*"
         addStringOption "samplesdir", "${supportRootFolder}/samples"
         addOption hdfOption
+        addOption sinceOption
     }
 
     exclude '**/BuildConfig.java'
@@ -336,18 +346,16 @@
 
 subprojects { subProject ->
     subProject.afterEvaluate { p ->
-        if (!p.hasProperty("noDocs") || !p.noDocs) {
-            if (p.hasProperty('android') && p.android.hasProperty('libraryVariants')) {
-                p.android.libraryVariants.all { v ->
-                    if (v.name == 'release') {
-                        registerForDocsTask(rootProject.generateDocs, p, v)
-                        registerForDocsTask(rootProject.generateApi, p, v)
-                        registerForDocsTask(rootProject.generateDiffs, p, v)
-                    }
+        if (p.hasProperty('android') && p.android.hasProperty('libraryVariants')) {
+            p.android.libraryVariants.all { v ->
+                if (v.name == 'release') {
+                    registerForDocsTask(rootProject.generateDocs, p, v)
+                    registerForDocsTask(rootProject.generateApi, p, v)
+                    registerForDocsTask(rootProject.generateDiffs, p, v)
                 }
-            } else if (p.hasProperty("compileJava")) {
-                registerJavaProjectForDocsTask(rootProject.generateDocs, p, p.compileJava)
             }
+        } else if (p.hasProperty("compileJava")) {
+            registerJavaProjectForDocsTask(rootProject.generateDocs, p, p.compileJava)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index 8b6505d..988da6d 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -32,6 +32,7 @@
 ext.init.prebuiltsRoot = "${init.checkoutRoot}/prebuilts"
 ext.init.prebuiltsRootUri = "file://${init.prebuiltsRoot}"
 ext.init.enablePublicRepos = System.getenv("ALLOW_PUBLIC_REPOS") != null
+ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
 
 ext.repoNames = ["${init.prebuiltsRoot}/gradle-plugin",
                  "${init.prebuiltsRoot}/tools/common/m2/repository",
@@ -75,10 +76,10 @@
 def setSdkInLocalPropertiesFile() {
     final String platform = OperatingSystem.current().isMacOsX() ? 'darwin' : 'linux'
     System.setProperty('android.dir', "${supportRootFolder}/../../")
+    ext.buildToolsVersion = '26.0.0'
     final String fullSdkPath = "${init.prebuiltsRoot}/fullsdk-${platform}"
     if (file(fullSdkPath).exists()) {
         gradle.ext.currentSdk = 26
-        ext.buildToolsVersion = '26.0.0'
         project.ext.androidJar = files("${fullSdkPath}/platforms/android-${gradle.ext.currentSdk}" +
                 "/android.jar")
         System.setProperty('android.home', "${init.prebuiltsRoot}/fullsdk-${platform}")
@@ -86,7 +87,6 @@
         props.write "sdk.dir=${fullSdkPath}"
     } else {
         gradle.ext.currentSdk = 'current'
-        ext.buildToolsVersion = '24.0.1'
         project.ext.androidJar = files("${init.prebuiltsRoot}/sdk/current/android.jar")
         File props = file("local.properties")
         props.write "android.dir=../../"
@@ -104,7 +104,7 @@
      *
      * The build server will copy the contents of DIST_DIR to somewhere and make it available.
      */
-    if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) {
+    if (ext.runningInBuildServer) {
         buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build')
                 .getCanonicalFile()
         project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()
@@ -122,6 +122,7 @@
     }
     ext.supportRepoOut = new File(buildDir, 'support_repo')
     ext.testApkDistOut = ext.distDir
+    ext.testResultsDistDir = new File(distDir, "host-test-reports")
     ext.docsDir = new File(buildDir, 'javadoc')
 }
 
@@ -130,7 +131,15 @@
     def lintTask = project.tasks.create("lint")
     subprojects {
         // Only modify Android projects.
-        if (project.name.equals('doclava') || project.name.equals('jdiff')) return;
+        if (project.name.equals('doclava') || project.name.equals('jdiff')) {
+            // disable tests and return
+            project.tasks.whenTaskAdded { task ->
+                if (task instanceof org.gradle.api.tasks.testing.Test) {
+                    task.enabled = false
+                }
+            }
+            return
+        }
 
         // Current SDK is set in studioCompat.gradle.
         project.ext.currentSdk = gradle.ext.currentSdk
@@ -269,11 +278,11 @@
 
                 task createSeparateZip(type: Zip, dependsOn: generateSourceProps) {
                     into archivesBaseName
-                    destinationDir project.parent.ext.distDir
+                    destinationDir rootProject.ext.distDir
                     baseName = project.group
-                    version = project.parent.ext.buildNumber
+                    version = rootProject.ext.buildNumber
                 }
-                project.parent.createArchive.dependsOn createSeparateZip
+                rootProject.createArchive.dependsOn createSeparateZip
 
                 // Before the upload, make sure the repo is ready.
                 release.dependsOn rootProject.tasks.prepareRepo
@@ -283,6 +292,52 @@
             }
         }
 
+        // Copy instrumentation test APKs and app APKs into the dist dir
+        // For test apks, they are uploaded only if we have java test sources.
+        // For regular app apks, they are uploaded only if they have java sources.
+        project.tasks.whenTaskAdded { task ->
+            if (task.name.startsWith("packageDebug")) {
+                def testApk = task.name.contains("AndroidTest")
+                task.doLast {
+                    def source = testApk ? project.android.sourceSets.androidTest
+                            : project.android.sourceSets.main
+                    if (task.hasProperty("outputFile") && !source.java.sourceFiles.isEmpty()) {
+                        copy {
+                            from(task.outputFile)
+                            into(rootProject.ext.testApkDistOut)
+                            rename { String fileName ->
+                                // multiple modules may have the same name so prefix the name with
+                                // the module's path to ensure it is unique.
+                                // e.g. palette-v7-debug-androidTest.apk becomes
+                                // support-palette-v7_palette-v7-debug-androidTest.apk
+                                "${project.getPath().replace(':', '-').substring(1)}_${fileName}"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // copy host side test results to DIST
+        project.tasks.whenTaskAdded { task ->
+            if (task instanceof org.gradle.api.tasks.testing.Test) {
+                def junitReport = task.reports.junitXml
+                if (junitReport.enabled) {
+                    def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) {
+                        destinationDir(testResultsDistDir)
+                        archiveName("${project.name}.zip")
+                    }
+                    if (project.rootProject.ext.runningInBuildServer) {
+                        task.ignoreFailures = true
+                    }
+                    task.finalizedBy zipTask
+                    task.doFirst {
+                        zipTask.from(junitReport.destination)
+                    }
+                }
+            }
+        }
+
         project.afterEvaluate {
             // The archivesBaseName isn't available initially, so set it now
             def createZipTask = project.tasks.findByName("createSeparateZip")
@@ -290,21 +345,6 @@
                 createZipTask.appendix = archivesBaseName
                 createZipTask.from versionDir()
             }
-
-            // Copy instrumentation test APK into the dist dir
-            def assembleTestTask = project.tasks.findByPath('assembleAndroidTest')
-            if (assembleTestTask != null) {
-                assembleTestTask.doLast {
-                    // If the project actually has some instrumentation tests, copy its APK
-                    if (!project.android.sourceSets.androidTest.java.sourceFiles.isEmpty()) {
-                        def pkgTask = project.tasks.findByPath('packageDebugAndroidTest')
-                        copy {
-                            from(pkgTask.outputFile)
-                            into(rootProject.ext.testApkDistOut)
-                        }
-                    }
-                }
-            }
         }
 
         project.afterEvaluate { p ->
diff --git a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
index 4844263..f1f6a04 100644
--- a/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
+++ b/buildSrc/src/main/groovy/android/support/SupportLibraryPlugin.groovy
@@ -89,8 +89,7 @@
         }
 
         // Library projects don't run lint by default, so set up dependency.
-        // Disabled temporarily until we switch to Android Gradle Plugin 2.3
-        // project.tasks.release.dependsOn project.tasks.lint
+        project.tasks.release.dependsOn project.tasks.lint
 
         // Java 8 is only fully supported on API 24+ and not all Java 8 features are binary
         // compatible with API < 24, so use Java 7 for both source AND target.
diff --git a/buildSrc/src/main/groovy/android/support/doclava/DoclavaMultilineJavadocOptionFileOption.java b/buildSrc/src/main/groovy/android/support/doclava/DoclavaMultilineJavadocOptionFileOption.java
index f3cd439..d4b1668 100644
--- a/buildSrc/src/main/groovy/android/support/doclava/DoclavaMultilineJavadocOptionFileOption.java
+++ b/buildSrc/src/main/groovy/android/support/doclava/DoclavaMultilineJavadocOptionFileOption.java
@@ -43,7 +43,7 @@
     public void setValue(List<List<String>> value) {
         final List<List<String>> args = getValue();
         if (args == null) {
-            super.setValue(value);
+            super.setValue(new ArrayList<List<String>>(value));
         } else {
             args.addAll(value);
         }
@@ -52,7 +52,7 @@
     public void add(List<String>... moreArgs) {
         final List<List<String>> args = getValue();
         if (args == null) {
-            super.setValue(Arrays.asList(moreArgs));
+            super.setValue(new ArrayList<List<String>>(Arrays.asList(moreArgs)));
         } else {
             args.addAll(Arrays.asList(moreArgs));
         }
diff --git a/compat/api24/android/support/v4/os/UserManagerCompatApi24.java b/compat/api24/android/support/v4/os/UserManagerCompatApi24.java
new file mode 100644
index 0000000..c8ef7c0
--- /dev/null
+++ b/compat/api24/android/support/v4/os/UserManagerCompatApi24.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.annotation.RequiresApi;
+
+@RequiresApi(24)
+class UserManagerCompatApi24 {
+    public static boolean isUserUnlocked(Context context) {
+        return context.getSystemService(UserManager.class).isUserUnlocked();
+    }
+}
diff --git a/compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java b/compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
index 435a76e..5b1bbc7 100644
--- a/compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
+++ b/compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
@@ -312,6 +312,7 @@
     /**
      * Returns the wrapped {@link Drawable}
      */
+    @Override
     public final Drawable getWrappedDrawable() {
         return mDrawable;
     }
@@ -319,6 +320,7 @@
     /**
      * Sets the current wrapped {@link Drawable}
      */
+    @Override
     public final void setWrappedDrawable(Drawable dr) {
         if (mDrawable != null) {
             mDrawable.setCallback(null);
@@ -367,6 +369,7 @@
             return newDrawable(null);
         }
 
+        @Override
         public abstract Drawable newDrawable(@Nullable Resources res);
 
         @Override
diff --git a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
index ce2d612..e2ea863 100644
--- a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
+++ b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
@@ -18,7 +18,7 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Build;
@@ -43,7 +43,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class AccessibilityServiceInfoApi16Impl extends AccessibilityServiceInfoBaseImpl {
         @Override
         public String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
@@ -51,7 +51,7 @@
         }
     }
 
-    @TargetApi(18)
+    @RequiresApi(18)
     static class AccessibilityServiceInfoApi18Impl
             extends AccessibilityServiceInfoApi16Impl {
         @Override
diff --git a/compat/java/android/support/v4/app/AppOpsManagerCompat.java b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
index 06da861..d67dbac 100644
--- a/compat/java/android/support/v4/app/AppOpsManagerCompat.java
+++ b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
 
 /**
  * Helper for accessing features in android.app.AppOpsManager
@@ -64,6 +65,7 @@
         }
     }
 
+    @RequiresApi(23)
     private static class AppOpsManager23 extends AppOpsManagerImpl {
         AppOpsManager23() {
         }
diff --git a/compat/java/android/support/v4/app/NotificationCompat.java b/compat/java/android/support/v4/app/NotificationCompat.java
index 5bc28c1..5d43871 100644
--- a/compat/java/android/support/v4/app/NotificationCompat.java
+++ b/compat/java/android/support/v4/app/NotificationCompat.java
@@ -20,6 +20,7 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -1029,6 +1030,7 @@
 
     static {
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             IMPL = new NotificationCompatApi26Impl();
         } else if (Build.VERSION.SDK_INT >= 24) {
             IMPL = new NotificationCompatApi24Impl();
diff --git a/compat/java/android/support/v4/app/NotificationManagerCompat.java b/compat/java/android/support/v4/app/NotificationManagerCompat.java
index d0b25aa..0cdd765 100644
--- a/compat/java/android/support/v4/app/NotificationManagerCompat.java
+++ b/compat/java/android/support/v4/app/NotificationManagerCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.app;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.Service;
@@ -188,7 +188,7 @@
         }
     }
 
-    @TargetApi(19)
+    @RequiresApi(19)
     static class ImplKitKat extends ImplBase {
         @Override
         public boolean areNotificationsEnabled(Context context,
@@ -197,7 +197,7 @@
         }
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     static class ImplApi24 extends ImplKitKat {
         @Override
         public boolean areNotificationsEnabled(Context context,
diff --git a/compat/java/android/support/v4/app/RemoteInput.java b/compat/java/android/support/v4/app/RemoteInput.java
index 2bf2f28..73eb388 100644
--- a/compat/java/android/support/v4/app/RemoteInput.java
+++ b/compat/java/android/support/v4/app/RemoteInput.java
@@ -22,6 +22,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.util.Log;
 
@@ -87,6 +88,7 @@
         return mChoices;
     }
 
+    @Override
     public Set<String> getAllowedDataTypes() {
         return mAllowedDataTypes;
     }
@@ -337,6 +339,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class ImplJellybean implements Impl {
         @Override
         public Bundle getResultsFromIntent(Intent intent) {
@@ -362,6 +365,7 @@
         }
     }
 
+    @RequiresApi(20)
     static class ImplApi20 implements Impl {
         @Override
         public Bundle getResultsFromIntent(Intent intent) {
diff --git a/compat/java/android/support/v4/app/ShareCompat.java b/compat/java/android/support/v4/app/ShareCompat.java
index de481ed..1f1c776 100644
--- a/compat/java/android/support/v4/app/ShareCompat.java
+++ b/compat/java/android/support/v4/app/ShareCompat.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.app;
 
+import android.support.annotation.RequiresApi;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -122,6 +123,7 @@
         }
     }
 
+    @RequiresApi(14)
     static class ShareCompatImplICS extends ShareCompatImplBase {
         @Override
         public void configureMenuItem(MenuItem item, IntentBuilder shareIntent) {
@@ -137,6 +139,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class ShareCompatImplJB extends ShareCompatImplICS {
         @Override
         public String escapeHtml(CharSequence html) {
diff --git a/compat/java/android/support/v4/content/ContentResolverCompat.java b/compat/java/android/support/v4/content/ContentResolverCompat.java
index 7efe79e..1aafc82 100644
--- a/compat/java/android/support/v4/content/ContentResolverCompat.java
+++ b/compat/java/android/support/v4/content/ContentResolverCompat.java
@@ -20,6 +20,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.support.v4.os.CancellationSignal;
 import android.support.v4.os.OperationCanceledException;
 
@@ -48,6 +49,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class ContentResolverCompatImplJB extends ContentResolverCompatImplBase {
         @Override
         public Cursor query(ContentResolver resolver, Uri uri, String[] projection,
@@ -73,8 +75,7 @@
 
     private static final ContentResolverCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 16) {
+        if (Build.VERSION.SDK_INT >= 16) {
             IMPL = new ContentResolverCompatImplJB();
         } else {
             IMPL = new ContentResolverCompatImplBase();
diff --git a/compat/java/android/support/v4/content/IntentCompat.java b/compat/java/android/support/v4/content/IntentCompat.java
index d34c914..9cc4fa3 100644
--- a/compat/java/android/support/v4/content/IntentCompat.java
+++ b/compat/java/android/support/v4/content/IntentCompat.java
@@ -50,8 +50,7 @@
 
     private static final IntentCompatBaseImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 15) {
+        if (Build.VERSION.SDK_INT >= 15) {
             IMPL = new IntentCompatApi15Impl();
         } else {
             IMPL = new IntentCompatBaseImpl();
diff --git a/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java b/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
index 2fe2e92..b6ac319 100644
--- a/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
+++ b/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
@@ -15,7 +15,7 @@
  */
 package android.support.v4.content.pm;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -47,7 +47,7 @@
 
     private ShortcutInfoCompat() { }
 
-    @TargetApi(25)
+    @RequiresApi(25)
     ShortcutInfo toShortcutInfo() {
         ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, mId)
                 .setShortLabel(mLabel)
diff --git a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
index 2261e86..732a14f 100644
--- a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
+++ b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.content.pm;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -46,8 +47,10 @@
      * @return {@code true} if the launcher supports {@link #requestPinShortcut},
      * {@code false} otherwise
      */
+    @SuppressLint("NewApi")
     public static boolean isRequestPinShortcutSupported(@NonNull Context context) {
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             return context.getSystemService(ShortcutManager.class).isRequestPinShortcutSupported();
         }
 
@@ -82,9 +85,11 @@
      * @see IntentSender
      * @see android.app.PendingIntent#getIntentSender()
      */
+    @SuppressLint("NewApi")
     public static boolean requestPinShortcut(@NonNull final Context context,
             @NonNull ShortcutInfoCompat shortcut, @Nullable final IntentSender callback) {
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             return context.getSystemService(ShortcutManager.class).requestPinShortcut(
                     shortcut.toShortcutInfo(), callback);
         }
@@ -125,10 +130,12 @@
      * @see Intent#ACTION_CREATE_SHORTCUT
      */
     @NonNull
+    @SuppressLint("NewApi")
     public static Intent createShortcutResultIntent(@NonNull Context context,
             @NonNull ShortcutInfoCompat shortcut) {
         Intent result = null;
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             result = context.getSystemService(ShortcutManager.class)
                     .createShortcutResultIntent(shortcut.toShortcutInfo());
         }
diff --git a/compat/java/android/support/v4/content/res/TypedArrayUtils.java b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
index 77d4672..7f8f3a2 100644
--- a/compat/java/android/support/v4/content/res/TypedArrayUtils.java
+++ b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -88,8 +88,8 @@
      * @return an int value in the {@link TypedArray} with the specified {@code resId}, or
      * {@code defaultValue} if it does not exist.
      */
-    public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
-            int resId, int defaultValue) {
+    public static int getNamedInt(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            String attrName, @StyleableRes int resId, int defaultValue) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return defaultValue;
@@ -117,6 +117,41 @@
     }
 
     /**
+     * Retrieves a resource ID attribute value. In addition to the styleable resource ID, we also
+     * make sure that the attribute name matches.
+     *
+     * @return a resource ID value in the {@link TypedArray} with the specified {@code resId}, or
+     * {@code defaultValue} if it does not exist.
+     */
+    @AnyRes
+    public static int getNamedResourceId(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            String attrName, @StyleableRes int resId, @AnyRes int defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getResourceId(resId, defaultValue);
+        }
+    }
+
+    /**
+     * Retrieves a string attribute value. In addition to the styleable resource ID, we also
+     * make sure that the attribute name matches.
+     *
+     * @return a string value in the {@link TypedArray} with the specified {@code resId}, or
+     * null if it does not exist.
+     */
+    public static String getNamedString(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            String attrName, @StyleableRes int resId) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return null;
+        } else {
+            return a.getString(resId);
+        }
+    }
+
+    /**
      * @return a boolean value of {@code index}. If it does not exist, a boolean value of
      * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
      */
diff --git a/compat/java/android/support/v4/graphics/BitmapCompat.java b/compat/java/android/support/v4/graphics/BitmapCompat.java
index e59e717..f417938 100644
--- a/compat/java/android/support/v4/graphics/BitmapCompat.java
+++ b/compat/java/android/support/v4/graphics/BitmapCompat.java
@@ -15,10 +15,9 @@
  */
 package android.support.v4.graphics;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.graphics.Bitmap;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 
 /**
  * Helper for accessing features in {@link android.graphics.Bitmap}
@@ -38,7 +37,7 @@
         }
     }
 
-    @TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
+    @RequiresApi(18)
     static class BitmapCompatApi18Impl extends BitmapCompatBaseImpl {
         @Override
         public boolean hasMipMap(Bitmap bitmap){
@@ -51,7 +50,7 @@
         }
     }
 
-    @TargetApi(VERSION_CODES.KITKAT)
+    @RequiresApi(19)
     static class BitmapCompatApi19Impl extends BitmapCompatApi18Impl {
         @Override
         public int getAllocationByteCount(Bitmap bitmap) {
@@ -64,10 +63,9 @@
      */
     static final BitmapCompatBaseImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new BitmapCompatApi19Impl();
-        } else if (version >= 18) {
+        } else if (Build.VERSION.SDK_INT >= 18) {
             IMPL = new BitmapCompatApi18Impl();
         } else {
             IMPL = new BitmapCompatBaseImpl();
diff --git a/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java b/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
index fa86926..53f43ef 100644
--- a/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
+++ b/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableContainer;
 import android.graphics.drawable.InsetDrawable;
+import android.os.Build;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -333,14 +334,13 @@
      */
     static final DrawableCompatBaseImpl IMPL;
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 23) {
+        if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new DrawableCompatApi23Impl();
-        } else if (version >= 21) {
+        } else if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new DrawableCompatApi21Impl();
-        } else if (version >= 19) {
+        } else if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new DrawableCompatApi19Impl();
-        } else if (version >= 17) {
+        } else if (Build.VERSION.SDK_INT >= 17) {
             IMPL = new DrawableCompatApi17Impl();
         } else {
             IMPL = new DrawableCompatBaseImpl();
diff --git a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
index 177c40a..50387e3 100644
--- a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
@@ -17,6 +17,8 @@
 package android.support.v4.hardware.display;
 
 import android.content.Context;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.view.Display;
 import android.view.WindowManager;
 
@@ -54,8 +56,7 @@
         synchronized (sInstances) {
             DisplayManagerCompat instance = sInstances.get(context);
             if (instance == null) {
-                final int version = android.os.Build.VERSION.SDK_INT;
-                if (version >= 17) {
+                if (Build.VERSION.SDK_INT >= 17) {
                     instance = new JellybeanMr1Impl(context);
                 } else {
                     instance = new LegacyImpl(context);
@@ -129,6 +130,7 @@
         }
     }
 
+    @RequiresApi(17)
     private static class JellybeanMr1Impl extends DisplayManagerCompat {
         private final Object mDisplayManagerObj;
 
diff --git a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
index 26045f7..2065bd3 100644
--- a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
 import android.support.v4.os.CancellationSignal;
 
 import java.security.Signature;
@@ -49,8 +50,7 @@
 
     static final FingerprintManagerCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 23) {
+        if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new Api23FingerprintManagerCompatImpl();
         } else {
             IMPL = new LegacyFingerprintManagerCompatImpl();
@@ -229,6 +229,7 @@
         }
     }
 
+    @RequiresApi(23)
     private static class Api23FingerprintManagerCompatImpl implements FingerprintManagerCompatImpl {
 
         public Api23FingerprintManagerCompatImpl() {
diff --git a/compat/java/android/support/v4/internal/view/SupportMenuItem.java b/compat/java/android/support/v4/internal/view/SupportMenuItem.java
index 86e497f..504b579 100644
--- a/compat/java/android/support/v4/internal/view/SupportMenuItem.java
+++ b/compat/java/android/support/v4/internal/view/SupportMenuItem.java
@@ -78,6 +78,7 @@
      * @see android.app.ActionBar
      * @see #setActionView(View)
      */
+    @Override
     void setShowAsAction(int actionEnum);
 
     /**
@@ -98,6 +99,7 @@
      * @see android.app.ActionBar
      * @see #setActionView(View)
      */
+    @Override
     MenuItem setShowAsActionFlags(int actionEnum);
 
     /**
@@ -112,6 +114,7 @@
      * @return This Item so additional setters can be called.
      * @see #setShowAsAction(int)
      */
+    @Override
     MenuItem setActionView(View view);
 
     /**
@@ -126,6 +129,7 @@
      * @return This Item so additional setters can be called.
      * @see #setShowAsAction(int)
      */
+    @Override
     MenuItem setActionView(int resId);
 
     /**
@@ -135,6 +139,7 @@
      * @see #setActionView(View)
      * @see #setShowAsAction(int)
      */
+    @Override
     View getActionView();
 
     /**
@@ -172,6 +177,7 @@
      *
      * @return true if the action view was expanded, false otherwise.
      */
+    @Override
     boolean expandActionView();
 
     /**
@@ -185,6 +191,7 @@
      *
      * @return true if the action view was collapsed, false otherwise.
      */
+    @Override
     boolean collapseActionView();
 
     /**
@@ -196,6 +203,7 @@
      * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
      * @see MenuItem.OnActionExpandListener
      */
+    @Override
     boolean isActionViewExpanded();
 
     /**
@@ -214,6 +222,7 @@
      * @param contentDescription The new content description.
      * @return This menu item instance for call chaining.
      */
+    @Override
     SupportMenuItem setContentDescription(CharSequence contentDescription);
 
     /**
@@ -221,6 +230,7 @@
      *
      * @return The content description.
      */
+    @Override
     CharSequence getContentDescription();
 
     /**
@@ -229,6 +239,7 @@
      * @param tooltipText The new tooltip text.
      * @return This menu item instance for call chaining.
      */
+    @Override
     SupportMenuItem setTooltipText(CharSequence tooltipText);
 
     /**
@@ -236,5 +247,6 @@
      *
      * @return The tooltip text.
      */
+    @Override
     CharSequence getTooltipText();
 }
\ No newline at end of file
diff --git a/compat/java/android/support/v4/net/TrafficStatsCompat.java b/compat/java/android/support/v4/net/TrafficStatsCompat.java
index 5c76b59..a9cb423 100644
--- a/compat/java/android/support/v4/net/TrafficStatsCompat.java
+++ b/compat/java/android/support/v4/net/TrafficStatsCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.net;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.net.TrafficStats;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
@@ -52,7 +52,7 @@
         }
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     static class TrafficStatsCompatApi24Impl extends TrafficStatsCompatBaseImpl {
         @Override
         public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
diff --git a/compat/java/android/support/v4/os/CancellationSignal.java b/compat/java/android/support/v4/os/CancellationSignal.java
index 41bdfe6..8a6a401 100644
--- a/compat/java/android/support/v4/os/CancellationSignal.java
+++ b/compat/java/android/support/v4/os/CancellationSignal.java
@@ -78,7 +78,7 @@
             if (listener != null) {
                 listener.onCancel();
             }
-            if (obj != null) {
+            if (obj != null && Build.VERSION.SDK_INT >= 16) {
                 CancellationSignalCompatJellybean.cancel(obj);
             }
         } finally {
diff --git a/compat/java/android/support/v4/os/EnvironmentCompat.java b/compat/java/android/support/v4/os/EnvironmentCompat.java
index 454065d..9781a8a 100644
--- a/compat/java/android/support/v4/os/EnvironmentCompat.java
+++ b/compat/java/android/support/v4/os/EnvironmentCompat.java
@@ -53,8 +53,7 @@
      *         {@link Environment#MEDIA_UNMOUNTABLE}.
      */
     public static String getStorageState(File path) {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             return EnvironmentCompatKitKat.getStorageState(path);
         }
 
diff --git a/compat/java/android/support/v4/os/ParcelableCompat.java b/compat/java/android/support/v4/os/ParcelableCompat.java
index 03051a2..663da56 100644
--- a/compat/java/android/support/v4/os/ParcelableCompat.java
+++ b/compat/java/android/support/v4/os/ParcelableCompat.java
@@ -49,14 +49,17 @@
             mCallbacks = callbacks;
         }
 
+        @Override
         public T createFromParcel(Parcel in) {
             return mCallbacks.createFromParcel(in, null);
         }
 
+        @Override
         public T createFromParcel(Parcel in, ClassLoader loader) {
             return mCallbacks.createFromParcel(in, loader);
         }
 
+        @Override
         public T[] newArray(int size) {
             return mCallbacks.newArray(size);
         }
diff --git a/compat/java/android/support/v4/os/UserManagerCompat.java b/compat/java/android/support/v4/os/UserManagerCompat.java
index 2321948..d73354f 100644
--- a/compat/java/android/support/v4/os/UserManagerCompat.java
+++ b/compat/java/android/support/v4/os/UserManagerCompat.java
@@ -18,13 +18,13 @@
 
 import android.content.Context;
 import android.os.Build;
-import android.os.UserManager;
 
 /**
  * Helper for accessing features in {@link android.os.UserManager} in a backwards compatible
  * fashion.
  */
 public class UserManagerCompat {
+
     private UserManagerCompat() {
     }
 
@@ -36,9 +36,10 @@
      */
     public static boolean isUserUnlocked(Context context) {
         if (Build.VERSION.SDK_INT >= 24) {
-            return context.getSystemService(UserManager.class).isUserUnlocked();
+            return UserManagerCompatApi24.isUserUnlocked(context);
         } else {
             return true;
         }
     }
+
 }
diff --git a/compat/java/android/support/v4/text/ICUCompat.java b/compat/java/android/support/v4/text/ICUCompat.java
index cd26961..d5ad0d6 100644
--- a/compat/java/android/support/v4/text/ICUCompat.java
+++ b/compat/java/android/support/v4/text/ICUCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.text;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.os.Build;
 import android.support.annotation.Nullable;
 
@@ -29,7 +29,7 @@
         }
     }
 
-    @TargetApi(23)
+    @RequiresApi(21)
     static class ICUCompatApi21Impl extends ICUCompatBaseImpl {
         @Override
         public String maximizeAndGetScript(Locale locale) {
@@ -40,8 +40,7 @@
     private static final ICUCompatBaseImpl IMPL;
 
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new ICUCompatApi21Impl();
         } else {
             IMPL = new ICUCompatBaseImpl();
diff --git a/compat/java/android/support/v4/text/TextUtilsCompat.java b/compat/java/android/support/v4/text/TextUtilsCompat.java
index 6acf644..9e190da 100644
--- a/compat/java/android/support/v4/text/TextUtilsCompat.java
+++ b/compat/java/android/support/v4/text/TextUtilsCompat.java
@@ -19,6 +19,7 @@
 import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
 import android.support.v4.view.ViewCompat;
 
 import java.util.Locale;
@@ -102,6 +103,7 @@
         }
     }
 
+    @RequiresApi(17)
     private static class TextUtilsCompatJellybeanMr1Impl extends TextUtilsCompatImpl {
         TextUtilsCompatJellybeanMr1Impl() {
         }
@@ -120,8 +122,7 @@
 
     private static final TextUtilsCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 17) { // JellyBean MR1
+        if (Build.VERSION.SDK_INT >= 17) { // JellyBean MR1
             IMPL = new TextUtilsCompatJellybeanMr1Impl();
         } else {
             IMPL = new TextUtilsCompatImpl();
diff --git a/compat/java/android/support/v4/view/GravityCompat.java b/compat/java/android/support/v4/view/GravityCompat.java
index cfcdd50..8131617 100644
--- a/compat/java/android/support/v4/view/GravityCompat.java
+++ b/compat/java/android/support/v4/view/GravityCompat.java
@@ -17,6 +17,7 @@
 
 package android.support.v4.view;
 
+import android.support.annotation.RequiresApi;
 import android.graphics.Rect;
 import android.os.Build;
 import android.view.Gravity;
@@ -59,6 +60,7 @@
         }
     }
 
+    @RequiresApi(17)
     static class GravityCompatImplJellybeanMr1 implements GravityCompatImpl {
         @Override
         public int getAbsoluteGravity(int gravity, int layoutDirection) {
@@ -86,8 +88,7 @@
 
     static final GravityCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 17) {
+        if (Build.VERSION.SDK_INT >= 17) {
             IMPL = new GravityCompatImplJellybeanMr1();
         } else {
             IMPL = new GravityCompatImplBase();
diff --git a/compat/java/android/support/v4/view/LayoutInflaterCompat.java b/compat/java/android/support/v4/view/LayoutInflaterCompat.java
index 8ffb9a8..1444b58 100644
--- a/compat/java/android/support/v4/view/LayoutInflaterCompat.java
+++ b/compat/java/android/support/v4/view/LayoutInflaterCompat.java
@@ -137,8 +137,7 @@
 
     static final LayoutInflaterCompatBaseImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new LayoutInflaterCompatApi21Impl();
         } else {
             IMPL = new LayoutInflaterCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/MarginLayoutParamsCompat.java b/compat/java/android/support/v4/view/MarginLayoutParamsCompat.java
index 4e5851e..84ad177 100644
--- a/compat/java/android/support/v4/view/MarginLayoutParamsCompat.java
+++ b/compat/java/android/support/v4/view/MarginLayoutParamsCompat.java
@@ -17,6 +17,7 @@
 
 package android.support.v4.view;
 
+import android.support.annotation.RequiresApi;
 import android.os.Build;
 import android.view.ViewGroup;
 
@@ -79,6 +80,7 @@
         }
     }
 
+    @RequiresApi(17)
     static class MarginLayoutParamsCompatImplJbMr1 implements MarginLayoutParamsCompatImpl {
 
         @Override
@@ -124,8 +126,7 @@
 
     static final MarginLayoutParamsCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 17) { // jb-mr1
+        if (Build.VERSION.SDK_INT >= 17) { // jb-mr1
             IMPL = new MarginLayoutParamsCompatImplJbMr1();
         } else {
             IMPL = new MarginLayoutParamsCompatImplBase();
diff --git a/compat/java/android/support/v4/view/MenuItemCompat.java b/compat/java/android/support/v4/view/MenuItemCompat.java
index 64d682c..d21be25 100644
--- a/compat/java/android/support/v4/view/MenuItemCompat.java
+++ b/compat/java/android/support/v4/view/MenuItemCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.view;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.support.v4.internal.view.SupportMenuItem;
 import android.support.v4.os.BuildCompat;
 import android.util.Log;
@@ -144,7 +144,7 @@
         }
     }
 
-    @TargetApi(26)
+    @RequiresApi(26)
     static class MenuItemCompatApi26Impl extends MenuItemCompatBaseImpl {
         @Override
         public void setContentDescription(MenuItem item, CharSequence contentDescription) {
@@ -173,6 +173,7 @@
     static final MenuVersionImpl IMPL;
     static {
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             IMPL = new MenuItemCompatApi26Impl();
         } else {
             IMPL = new MenuItemCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/PointerIconCompat.java b/compat/java/android/support/v4/view/PointerIconCompat.java
index cea4dfb..77cda4f 100644
--- a/compat/java/android/support/v4/view/PointerIconCompat.java
+++ b/compat/java/android/support/v4/view/PointerIconCompat.java
@@ -18,9 +18,11 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
+import android.support.annotation.RequiresApi;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.os.Build;
 import android.support.annotation.RestrictTo;
 import android.support.v4.os.BuildCompat;
 
@@ -136,6 +138,7 @@
         }
     }
 
+    @RequiresApi(24)
     static class Api24PointerIconCompatImpl extends BasePointerIconCompatImpl {
         @Override
         public Object getSystemIcon(Context context, int style) {
@@ -155,7 +158,7 @@
 
     static final PointerIconCompatImpl IMPL;
     static {
-        if (BuildCompat.isAtLeastN()) {
+        if (Build.VERSION.SDK_INT >= 24) {
             IMPL = new Api24PointerIconCompatImpl();
         } else {
             IMPL = new BasePointerIconCompatImpl();
diff --git a/compat/java/android/support/v4/view/ScaleGestureDetectorCompat.java b/compat/java/android/support/v4/view/ScaleGestureDetectorCompat.java
index 30d0ca1..9141fb1 100644
--- a/compat/java/android/support/v4/view/ScaleGestureDetectorCompat.java
+++ b/compat/java/android/support/v4/view/ScaleGestureDetectorCompat.java
@@ -16,6 +16,9 @@
 
 package android.support.v4.view;
 
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+
 /**
  * Helper for accessing features in <code>ScaleGestureDetector</code> introduced
  * after API level 19 (KitKat) in a backwards compatible fashion.
@@ -45,6 +48,7 @@
         }
     }
 
+    @RequiresApi(19)
     private static class ScaleGestureDetectorCompatKitKatImpl implements ScaleGestureDetectorImpl {
         ScaleGestureDetectorCompatKitKatImpl() {
         }
@@ -61,8 +65,7 @@
     }
 
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 19) { // KitKat
+        if (Build.VERSION.SDK_INT >= 19) { // KitKat
             IMPL = new ScaleGestureDetectorCompatKitKatImpl();
         } else {
             IMPL = new BaseScaleGestureDetectorImpl();
diff --git a/compat/java/android/support/v4/view/ViewCompat.java b/compat/java/android/support/v4/view/ViewCompat.java
index d792b40..91311be 100644
--- a/compat/java/android/support/v4/view/ViewCompat.java
+++ b/compat/java/android/support/v4/view/ViewCompat.java
@@ -19,7 +19,7 @@
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
 import android.animation.ValueAnimator;
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -926,7 +926,7 @@
         }
     }
 
-    @TargetApi(15)
+    @RequiresApi(15)
     static class ViewCompatApi15Impl extends ViewCompatBaseImpl {
         @Override
         public boolean hasOnClickListeners(View view) {
@@ -934,7 +934,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class ViewCompatApi16Impl extends ViewCompatApi15Impl {
         @Override
         public boolean hasTransientState(View view) {
@@ -1025,7 +1025,7 @@
         }
     }
 
-    @TargetApi(17)
+    @RequiresApi(17)
     static class ViewCompatApi17Impl extends ViewCompatApi16Impl {
 
         @Override
@@ -1084,7 +1084,7 @@
         }
     }
 
-    @TargetApi(18)
+    @RequiresApi(18)
     static class ViewCompatApi18Impl extends ViewCompatApi17Impl {
         @Override
         public void setClipBounds(View view, Rect clipBounds) {
@@ -1102,7 +1102,7 @@
         }
     }
 
-    @TargetApi(19)
+    @RequiresApi(19)
     static class ViewCompatApi19Impl extends ViewCompatApi18Impl {
         @Override
         public int getAccessibilityLiveRegion(View view) {
@@ -1135,7 +1135,7 @@
         }
     }
 
-    @TargetApi(21)
+    @RequiresApi(21)
     static class ViewCompatApi21Impl extends ViewCompatApi19Impl {
         private static ThreadLocal<Rect> sThreadLocalRect;
 
@@ -1390,7 +1390,7 @@
         }
     }
 
-    @TargetApi(23)
+    @RequiresApi(23)
     static class ViewCompatApi23Impl extends ViewCompatApi21Impl {
         @Override
         public void setScrollIndicators(View view, int indicators) {
@@ -1419,7 +1419,7 @@
         }
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     static class ViewCompatApi24Impl extends ViewCompatApi23Impl {
         @Override
         public void dispatchStartTemporaryDetach(View view) {
@@ -1454,7 +1454,7 @@
         }
     }
 
-    @TargetApi(26)
+    @RequiresApi(26)
     static class ViewCompatApi26Impl extends ViewCompatApi24Impl {
         @Override
         public void setTooltipText(View view, CharSequence tooltipText) {
@@ -1464,24 +1464,24 @@
 
     static final ViewCompatBaseImpl IMPL;
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
         if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             IMPL = new ViewCompatApi26Impl();
-        } else if (version >= 24) {
+        } else if (Build.VERSION.SDK_INT >= 24) {
             IMPL = new ViewCompatApi24Impl();
-        } else if (version >= 23) {
+        } else if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new ViewCompatApi23Impl();
-        } else if (version >= 21) {
+        } else if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new ViewCompatApi21Impl();
-        } else if (version >= 19) {
+        } else if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new ViewCompatApi19Impl();
-        } else if (version >= 18) {
+        } else if (Build.VERSION.SDK_INT >= 18) {
             IMPL = new ViewCompatApi18Impl();
-        } else if (version >= 17) {
+        } else if (Build.VERSION.SDK_INT >= 17) {
             IMPL = new ViewCompatApi17Impl();
-        } else if (version >= 16) {
+        } else if (Build.VERSION.SDK_INT >= 16) {
             IMPL = new ViewCompatApi16Impl();
-        } else if (version >= 15) {
+        } else if (Build.VERSION.SDK_INT >= 15) {
             IMPL = new ViewCompatApi15Impl();
         } else {
             IMPL = new ViewCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/ViewGroupCompat.java b/compat/java/android/support/v4/view/ViewGroupCompat.java
index 39046a3..11706b0 100644
--- a/compat/java/android/support/v4/view/ViewGroupCompat.java
+++ b/compat/java/android/support/v4/view/ViewGroupCompat.java
@@ -101,10 +101,9 @@
 
     static final ViewGroupCompatBaseImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new ViewGroupCompatApi21Impl();
-        } else if (version >= 18) {
+        } else if (Build.VERSION.SDK_INT >= 18) {
             IMPL = new ViewGroupCompatApi18Impl();
         } else {
             IMPL = new ViewGroupCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/ViewParentCompat.java b/compat/java/android/support/v4/view/ViewParentCompat.java
index 53ff8dd..f54a693 100644
--- a/compat/java/android/support/v4/view/ViewParentCompat.java
+++ b/compat/java/android/support/v4/view/ViewParentCompat.java
@@ -190,10 +190,9 @@
 
     static final ViewParentCompatBaseImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new ViewParentCompatApi21Impl();
-        } else if (version >= 19) {
+        } else if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new ViewParentCompatApi19Impl();
         } else {
             IMPL = new ViewParentCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/ViewPropertyAnimatorCompat.java b/compat/java/android/support/v4/view/ViewPropertyAnimatorCompat.java
index 117a4d6..48e6348 100644
--- a/compat/java/android/support/v4/view/ViewPropertyAnimatorCompat.java
+++ b/compat/java/android/support/v4/view/ViewPropertyAnimatorCompat.java
@@ -15,7 +15,7 @@
  */
 package android.support.v4.view;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.os.Build;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -181,7 +181,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class ViewPropertyAnimatorCompatApi16Impl extends ViewPropertyAnimatorCompatBaseImpl {
 
         @Override
@@ -205,7 +205,7 @@
         }
     }
 
-    @TargetApi(18)
+    @RequiresApi(18)
     static class ViewPropertyAnimatorCompatApi18Impl extends ViewPropertyAnimatorCompatApi16Impl {
 
         @Override
@@ -214,7 +214,7 @@
         }
     }
 
-    @TargetApi(19)
+    @RequiresApi(19)
     static class ViewPropertyAnimatorCompatApi19Impl extends ViewPropertyAnimatorCompatApi18Impl {
         @Override
         public void setUpdateListener(ViewPropertyAnimatorCompat vpa, View view,
@@ -223,7 +223,7 @@
         }
     }
 
-    @TargetApi(21)
+    @RequiresApi(21)
     static class ViewPropertyAnimatorCompatApi21Impl extends
             ViewPropertyAnimatorCompatApi19Impl {
         @Override
diff --git a/compat/java/android/support/v4/view/WindowInsetsCompat.java b/compat/java/android/support/v4/view/WindowInsetsCompat.java
index 79befe9..8d83a2c 100644
--- a/compat/java/android/support/v4/view/WindowInsetsCompat.java
+++ b/compat/java/android/support/v4/view/WindowInsetsCompat.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Rect;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 
 /**
  * Describes a set of insets for window content.
@@ -144,6 +145,7 @@
         }
     }
 
+    @RequiresApi(20)
     private static class WindowInsetsCompatApi20Impl extends WindowInsetsCompatBaseImpl {
         WindowInsetsCompatApi20Impl() {
         }
@@ -202,6 +204,7 @@
         }
     }
 
+    @RequiresApi(21)
     private static class WindowInsetsCompatApi21Impl extends WindowInsetsCompatApi20Impl {
         WindowInsetsCompatApi21Impl() {
         }
@@ -251,10 +254,9 @@
 
     private static final WindowInsetsCompatImpl IMPL;
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new WindowInsetsCompatApi21Impl();
-        } else if (version >= 20) {
+        } else if (Build.VERSION.SDK_INT >= 20) {
             IMPL = new WindowInsetsCompatApi20Impl();
         } else {
             IMPL = new WindowInsetsCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
index 0941fe6..c06104b 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
@@ -17,6 +17,7 @@
 package android.support.v4.view.accessibility;
 
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -83,6 +84,7 @@
         }
     }
 
+    @RequiresApi(14)
     static class AccessibilityEventIcsImpl extends AccessibilityEventStubImpl {
 
         @Override
@@ -101,6 +103,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class AccessibilityEventJellyBeanImpl extends AccessibilityEventIcsImpl {
         @Override
         public void setMovementGranularity(AccessibilityEvent event, int granularity) {
@@ -123,6 +126,7 @@
         }
     }
 
+    @RequiresApi(19)
     static class AccessibilityEventKitKatImpl extends AccessibilityEventJellyBeanImpl {
 
         @Override
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
index 544091a..b7581cf 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.support.v4.view.accessibility.AccessibilityManagerCompatIcs.AccessibilityStateChangeListenerBridge;
 import android.support.v4.view.accessibility.AccessibilityManagerCompatIcs.AccessibilityStateChangeListenerWrapper;
 import android.support.v4.view.accessibility.AccessibilityManagerCompatKitKat.TouchExplorationStateChangeListenerBridge;
@@ -108,6 +109,7 @@
         }
     }
 
+    @RequiresApi(14)
     static class AccessibilityManagerIcsImpl extends AccessibilityManagerStubImpl {
         @Override
         public AccessibilityStateChangeListenerWrapper newAccessibilityStateChangeListener(
@@ -154,6 +156,7 @@
         }
     }
 
+    @RequiresApi(19)
     static class AccessibilityManagerKitKatImpl extends AccessibilityManagerIcsImpl {
         @Override
         public TouchExplorationStateChangeListenerWrapper newTouchExplorationStateChangeListener(
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
index 6119021..632eae9 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
@@ -18,7 +18,7 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
@@ -1096,7 +1096,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class AccessibilityNodeInfoApi16Impl extends AccessibilityNodeInfoBaseImpl {
         @Override
         public AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
@@ -1164,7 +1164,7 @@
         }
     }
 
-    @TargetApi(17)
+    @RequiresApi(17)
     static class AccessibilityNodeInfoApi17Impl extends AccessibilityNodeInfoApi16Impl {
 
         @Override
@@ -1198,7 +1198,7 @@
         }
     }
 
-    @TargetApi(18)
+    @RequiresApi(18)
     static class AccessibilityNodeInfoApi18Impl extends AccessibilityNodeInfoApi17Impl {
 
         @Override
@@ -1248,7 +1248,7 @@
         }
     }
 
-    @TargetApi(19)
+    @RequiresApi(19)
     static class AccessibilityNodeInfoApi19Impl extends AccessibilityNodeInfoApi18Impl {
         private static final String ROLE_DESCRIPTION_KEY =
                 "AccessibilityNodeInfo.roleDescription";
@@ -1432,7 +1432,7 @@
         }
     }
 
-    @TargetApi(21)
+    @RequiresApi(21)
     static class AccessibilityNodeInfoApi21Impl extends AccessibilityNodeInfoApi19Impl {
         @Override
         public Object newAccessibilityAction(int actionId, CharSequence label) {
@@ -1525,7 +1525,7 @@
         }
     }
 
-    @TargetApi(22)
+    @RequiresApi(22)
     static class AccessibilityNodeInfoApi22Impl extends AccessibilityNodeInfoApi21Impl {
         @Override
         public Object getTraversalBefore(AccessibilityNodeInfo info) {
@@ -1560,7 +1560,7 @@
         }
     }
 
-    @TargetApi(23)
+    @RequiresApi(23)
     static class AccessibilityNodeInfoApi23Impl extends AccessibilityNodeInfoApi22Impl {
         @Override
         public Object getActionScrollToPosition() {
@@ -1608,7 +1608,7 @@
         }
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     static class AccessibilityNodeInfoApi24Impl extends AccessibilityNodeInfoApi23Impl {
         @Override
         public Object getActionSetProgress() {
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
index 48f2f5c..c336585 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityNodeProviderCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.view.accessibility;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
@@ -41,7 +41,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     private static class AccessibilityNodeProviderJellyBeanImpl
             extends AccessibilityNodeProviderStubImpl {
         AccessibilityNodeProviderJellyBeanImpl() {
@@ -91,7 +91,7 @@
         }
     }
 
-    @TargetApi(19)
+    @RequiresApi(19)
     private static class AccessibilityNodeProviderKitKatImpl
             extends AccessibilityNodeProviderStubImpl {
         AccessibilityNodeProviderKitKatImpl() {
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityRecordCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityRecordCompat.java
index 9d00c58..695be96 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityRecordCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityRecordCompat.java
@@ -18,6 +18,7 @@
 
 import android.os.Build;
 import android.os.Parcelable;
+import android.support.annotation.RequiresApi;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
@@ -311,6 +312,7 @@
         }
     }
 
+    @RequiresApi(14)
     static class AccessibilityRecordIcsImpl extends AccessibilityRecordStubImpl {
         @Override
         public Object obtain() {
@@ -519,6 +521,7 @@
         }
     }
 
+    @RequiresApi(15)
     static class AccessibilityRecordIcsMr1Impl extends AccessibilityRecordIcsImpl {
         @Override
         public int getMaxScrollX(Object record) {
@@ -541,6 +544,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class AccessibilityRecordJellyBeanImpl extends AccessibilityRecordIcsMr1Impl {
         @Override
         public void setSource(Object record, View root, int virtualDescendantId) {
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java
index bec1dd5..b8d90c5 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Rect;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 
 /**
  * Helper for accessing {@link android.view.accessibility.AccessibilityWindowInfo}
@@ -128,6 +129,7 @@
         }
     }
 
+    @RequiresApi(21)
     private static class AccessibilityWindowInfoApi21Impl extends AccessibilityWindowInfoStubImpl {
         AccessibilityWindowInfoApi21Impl() {
         }
@@ -203,6 +205,7 @@
         }
     }
 
+    @RequiresApi(24)
     private static class AccessibilityWindowInfoApi24Impl extends AccessibilityWindowInfoApi21Impl {
         AccessibilityWindowInfoApi24Impl() {
         }
diff --git a/compat/java/android/support/v4/widget/CompoundButtonCompat.java b/compat/java/android/support/v4/widget/CompoundButtonCompat.java
index f52a55c..25d876e 100644
--- a/compat/java/android/support/v4/widget/CompoundButtonCompat.java
+++ b/compat/java/android/support/v4/widget/CompoundButtonCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.widget;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
@@ -38,10 +38,9 @@
     private static final CompoundButtonCompatBaseImpl IMPL;
 
     static {
-        final int sdk = Build.VERSION.SDK_INT;
-        if (sdk >= 23) {
+        if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new CompoundButtonCompatApi23Impl();
-        } else if (sdk >= 21) {
+        } else if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new CompoundButtonCompatApi21Impl();
         } else {
             IMPL = new CompoundButtonCompatBaseImpl();
@@ -103,7 +102,7 @@
         }
     }
 
-    @TargetApi(21)
+    @RequiresApi(21)
     static class CompoundButtonCompatApi21Impl extends CompoundButtonCompatBaseImpl {
         @Override
         public void setButtonTintList(CompoundButton button, ColorStateList tint) {
@@ -126,7 +125,7 @@
         }
     }
 
-    @TargetApi(23)
+    @RequiresApi(23)
     static class CompoundButtonCompatApi23Impl extends CompoundButtonCompatApi21Impl {
         @Override
         public Drawable getButtonDrawable(CompoundButton button) {
diff --git a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
index 8d34312..9901f04 100644
--- a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.widget;
 
+import android.support.annotation.RequiresApi;
+import android.os.Build;
 import android.view.View;
 import android.view.View.OnTouchListener;
 
@@ -44,6 +46,7 @@
     /**
      * Interface implementation for devices with at least KitKat APIs.
      */
+    @RequiresApi(19)
     static class KitKatListPopupWindowImpl extends BaseListPopupWindowImpl {
         @Override
         public OnTouchListener createDragToOpenListener(Object listPopupWindow, View src) {
@@ -56,8 +59,7 @@
      */
     static final ListPopupWindowImpl IMPL;
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new KitKatListPopupWindowImpl();
         } else {
             IMPL = new BaseListPopupWindowImpl();
diff --git a/compat/java/android/support/v4/widget/PopupMenuCompat.java b/compat/java/android/support/v4/widget/PopupMenuCompat.java
index 3651429..2de7cc8 100644
--- a/compat/java/android/support/v4/widget/PopupMenuCompat.java
+++ b/compat/java/android/support/v4/widget/PopupMenuCompat.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.widget;
 
+import android.support.annotation.RequiresApi;
+import android.os.Build;
 import android.view.View.OnTouchListener;
 
 /**
@@ -43,6 +45,7 @@
     /**
      * Interface implementation for devices with at least KitKat APIs.
      */
+    @RequiresApi(19)
     static class KitKatPopupMenuImpl extends BasePopupMenuImpl {
         @Override
         public OnTouchListener getDragToOpenListener(Object popupMenu) {
@@ -55,8 +58,7 @@
      */
     static final PopupMenuImpl IMPL;
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new KitKatPopupMenuImpl();
         } else {
             IMPL = new BasePopupMenuImpl();
diff --git a/compat/java/android/support/v4/widget/PopupWindowCompat.java b/compat/java/android/support/v4/widget/PopupWindowCompat.java
index 2047662..698e718 100644
--- a/compat/java/android/support/v4/widget/PopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/PopupWindowCompat.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.widget;
 
+import android.support.annotation.RequiresApi;
+import android.os.Build;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
 import android.view.Gravity;
@@ -122,6 +124,7 @@
     /**
      * Interface implementation for devices with at least KitKat APIs.
      */
+    @RequiresApi(19)
     static class KitKatPopupWindowImpl extends BasePopupWindowImpl {
         @Override
         public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
@@ -130,6 +133,7 @@
         }
     }
 
+    @RequiresApi(21)
     static class Api21PopupWindowImpl extends KitKatPopupWindowImpl {
         @Override
         public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
@@ -142,6 +146,7 @@
         }
     }
 
+    @RequiresApi(23)
     static class Api23PopupWindowImpl extends Api21PopupWindowImpl {
         @Override
         public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
@@ -169,12 +174,11 @@
      */
     static final PopupWindowImpl IMPL;
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 23) {
+        if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new Api23PopupWindowImpl();
-        } else if (version >= 21) {
+        } else if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new Api21PopupWindowImpl();
-        } else if (version >= 19) {
+        } else if (Build.VERSION.SDK_INT >= 19) {
             IMPL = new KitKatPopupWindowImpl();
         } else {
             IMPL = new BasePopupWindowImpl();
diff --git a/compat/java/android/support/v4/widget/TextViewCompat.java b/compat/java/android/support/v4/widget/TextViewCompat.java
index f6b759a..dbf8dbd 100644
--- a/compat/java/android/support/v4/widget/TextViewCompat.java
+++ b/compat/java/android/support/v4/widget/TextViewCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.widget;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.support.annotation.DrawableRes;
@@ -135,7 +135,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class TextViewCompatApi16Impl extends TextViewCompatBaseImpl {
         @Override
         public int getMaxLines(TextView textView) {
@@ -148,7 +148,7 @@
         }
     }
 
-    @TargetApi(17)
+    @RequiresApi(17)
     static class TextViewCompatApi17Impl extends TextViewCompatApi16Impl {
         @Override
         public void setCompoundDrawablesRelative(@NonNull TextView textView,
@@ -191,7 +191,7 @@
         }
     }
 
-    @TargetApi(18)
+    @RequiresApi(18)
     static class TextViewCompatApi18Impl extends TextViewCompatApi17Impl {
         @Override
         public void setCompoundDrawablesRelative(@NonNull TextView textView,
@@ -220,7 +220,7 @@
         }
     }
 
-    @TargetApi(23)
+    @RequiresApi(23)
     static class TextViewCompatApi23Impl extends TextViewCompatApi18Impl {
         @Override
         public void setTextAppearance(@NonNull TextView textView, @StyleRes int resId) {
diff --git a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
index d27d11b..feee689 100644
--- a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
+++ b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
@@ -139,6 +139,7 @@
             return b;
         }
 
+        @Override
         public Notification build() {
             Notification notif = b.build();
             // Merge in developer provided extras, but let the values already set
diff --git a/compat/tests/java/android/support/v4/app/NotificationCompatTest.java b/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
index 5b2a79b..3b953ff 100644
--- a/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
+++ b/compat/tests/java/android/support/v4/app/NotificationCompatTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.TargetApi;
 import android.app.Notification;
 import android.content.Context;
 import android.support.test.filters.SdkSuppress;
@@ -108,6 +109,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesTrue()
             throws Throwable {
@@ -121,6 +123,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesFalse()
             throws Throwable {
diff --git a/compat/tests/java/android/support/v4/app/RemoteInputTest.java b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
index 4c3d81b..55d6cca 100644
--- a/compat/tests/java/android/support/v4/app/RemoteInputTest.java
+++ b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.TargetApi;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -95,6 +96,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataResultsFromIntent() throws Throwable {
         Uri uri = Uri.parse("Some Uri");
@@ -108,6 +110,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testRemoteInputBuilder_addAndGetTextResultsFromIntent() throws Throwable {
         CharSequence charSequence = "value doesn't matter";
@@ -123,6 +126,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataAndTextResultsFromIntentDataFirst()
             throws Throwable {
@@ -149,6 +153,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 17)
+    @TargetApi(17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataAndTextResultsFromIntentTextFirst()
             throws Throwable {
diff --git a/compat/tests/java/android/support/v4/testutils/TestUtils.java b/compat/tests/java/android/support/v4/testutils/TestUtils.java
index 0bb8e1f..e44448d 100644
--- a/compat/tests/java/android/support/v4/testutils/TestUtils.java
+++ b/compat/tests/java/android/support/v4/testutils/TestUtils.java
@@ -27,8 +27,6 @@
 import android.graphics.drawable.Drawable;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
 
 import junit.framework.Assert;
 
diff --git a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
index 775eb1d..51bb7d0 100644
--- a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
+++ b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
@@ -49,6 +49,7 @@
             "(test:)?[a-zA-Z0-9]+(\\.pattern)?");
 
     private MatchFilter mMatchFilterStartWithDot = new MatchFilter() {
+        @Override
         public final boolean acceptMatch(final CharSequence s, final int start, final int end) {
             if (start == 0) {
                 return true;
@@ -63,6 +64,7 @@
     };
 
     private TransformFilter mTransformFilterUpperChar = new TransformFilter() {
+        @Override
         public final String transformUrl(final Matcher match, String url) {
             StringBuilder buffer = new StringBuilder();
             String matchingRegion = match.group();
diff --git a/core-ui/java/android/support/v4/view/ViewPager.java b/core-ui/java/android/support/v4/view/ViewPager.java
index 4c1e497..bec05fe 100644
--- a/core-ui/java/android/support/v4/view/ViewPager.java
+++ b/core-ui/java/android/support/v4/view/ViewPager.java
@@ -2680,6 +2680,7 @@
      * @return Whether this ViewPager can be scrolled in the specified direction. It will always
      *         return false if the specified direction is 0.
      */
+    @Override
     public boolean canScrollHorizontally(int direction) {
         if (mAdapter == null) {
             return false;
diff --git a/core-ui/java/android/support/v4/widget/DrawerLayout.java b/core-ui/java/android/support/v4/widget/DrawerLayout.java
index 74c6bf4..c3cb8f7 100644
--- a/core-ui/java/android/support/v4/widget/DrawerLayout.java
+++ b/core-ui/java/android/support/v4/widget/DrawerLayout.java
@@ -17,6 +17,7 @@
 
 package android.support.v4.widget;
 
+import android.support.annotation.RequiresApi;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -321,6 +322,7 @@
         }
     }
 
+    @RequiresApi(21)
     static class DrawerLayoutCompatImplApi21 implements DrawerLayoutCompatImpl {
         @Override
         public void configureApplyInsets(View drawerLayout) {
@@ -349,8 +351,7 @@
     }
 
     static {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             IMPL = new DrawerLayoutCompatImplApi21();
         } else {
             IMPL = new DrawerLayoutCompatImplBase();
@@ -1330,6 +1331,7 @@
         invalidate();
     }
 
+    @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         resolveShadowDrawables();
     }
diff --git a/core-ui/java/android/support/v4/widget/MaterialProgressDrawable.java b/core-ui/java/android/support/v4/widget/MaterialProgressDrawable.java
index 12b3a74..cad36d9 100644
--- a/core-ui/java/android/support/v4/widget/MaterialProgressDrawable.java
+++ b/core-ui/java/android/support/v4/widget/MaterialProgressDrawable.java
@@ -235,6 +235,7 @@
         mRing.setAlpha(alpha);
     }
 
+    @Override
     public int getAlpha() {
         return mRing.getAlpha();
     }
diff --git a/core-ui/java/android/support/v4/widget/NestedScrollView.java b/core-ui/java/android/support/v4/widget/NestedScrollView.java
index 709165f..d65a528 100644
--- a/core-ui/java/android/support/v4/widget/NestedScrollView.java
+++ b/core-ui/java/android/support/v4/widget/NestedScrollView.java
@@ -312,6 +312,7 @@
 
     // ScrollView import
 
+    @Override
     public boolean shouldDelayChildPressedState() {
         return true;
     }
@@ -891,6 +892,7 @@
         }
     }
 
+    @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
         if ((event.getSource() & InputDeviceCompat.SOURCE_CLASS_POINTER) != 0) {
             switch (event.getAction()) {
diff --git a/core-ui/java/android/support/v4/widget/SlidingPaneLayout.java b/core-ui/java/android/support/v4/widget/SlidingPaneLayout.java
index 82b974c..0e482d7 100644
--- a/core-ui/java/android/support/v4/widget/SlidingPaneLayout.java
+++ b/core-ui/java/android/support/v4/widget/SlidingPaneLayout.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.widget;
 
+import android.support.annotation.RequiresApi;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -197,10 +198,9 @@
     static final SlidingPanelLayoutImpl IMPL;
 
     static {
-        final int deviceVersion = Build.VERSION.SDK_INT;
-        if (deviceVersion >= 17) {
+        if (Build.VERSION.SDK_INT >= 17) {
             IMPL = new SlidingPanelLayoutImplJBMR1();
-        } else if (deviceVersion >= 16) {
+        } else if (Build.VERSION.SDK_INT >= 16) {
             IMPL = new SlidingPanelLayoutImplJB();
         } else {
             IMPL = new SlidingPanelLayoutImplBase();
@@ -1507,6 +1507,7 @@
         }
     }
 
+    @RequiresApi(16)
     static class SlidingPanelLayoutImplJB extends SlidingPanelLayoutImplBase {
         /*
          * Private API hacks! Nasty! Bad!
@@ -1551,6 +1552,7 @@
         }
     }
 
+    @RequiresApi(17)
     static class SlidingPanelLayoutImplJBMR1 extends SlidingPanelLayoutImplBase {
         @Override
         public void invalidateChildRegion(SlidingPaneLayout parent, View child) {
diff --git a/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java b/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
index a38afa4..d515561 100644
--- a/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
+++ b/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
@@ -276,6 +276,7 @@
         }
     }
 
+    @Override
     public int getAlpha() {
         return mPaint.getAlpha();
     }
@@ -286,6 +287,7 @@
         invalidateSelf();
     }
 
+    @Override
     public ColorFilter getColorFilter() {
         return mPaint.getColorFilter();
     }
diff --git a/core-utils/java/android/support/v4/app/NavUtils.java b/core-utils/java/android/support/v4/app/NavUtils.java
index ae1bb10..b5638c5 100644
--- a/core-utils/java/android/support/v4/app/NavUtils.java
+++ b/core-utils/java/android/support/v4/app/NavUtils.java
@@ -16,7 +16,8 @@
 
 package android.support.v4.app;
 
-import android.annotation.TargetApi;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -93,7 +94,7 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class NavUtilsImplJB extends NavUtilsImplBase {
 
         @Override
@@ -134,8 +135,7 @@
     private static final NavUtilsImpl IMPL;
 
     static {
-        final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 16) {
+        if (Build.VERSION.SDK_INT >= 16) {
             IMPL = new NavUtilsImplJB();
         } else {
             IMPL = new NavUtilsImplBase();
diff --git a/core-utils/java/android/support/v4/app/TaskStackBuilder.java b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
index d95e1a4..dc9a2dc 100644
--- a/core-utils/java/android/support/v4/app/TaskStackBuilder.java
+++ b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
@@ -16,7 +16,7 @@
 
 package android.support.v4.app;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -82,8 +82,9 @@
         }
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     static class TaskStackBuilderApi16Impl extends TaskStackBuilderBaseImpl {
+        @Override
         public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
                 int flags, Bundle options) {
             intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -270,6 +271,7 @@
     /**
      * @deprecated Use editIntentAt instead
      */
+    @Override
     @Deprecated
     public Iterator<Intent> iterator() {
         return mIntents.iterator();
diff --git a/core-utils/java/android/support/v4/math/MathUtils.java b/core-utils/java/android/support/v4/math/MathUtils.java
index e66b2c2..25f8644 100644
--- a/core-utils/java/android/support/v4/math/MathUtils.java
+++ b/core-utils/java/android/support/v4/math/MathUtils.java
@@ -21,6 +21,8 @@
  */
 public class MathUtils {
 
+    private MathUtils() {}
+
     /**
      * This method takes a numerical value and ensures it fits in a given numerical range. If the
      * number is smaller than the minimum required by the range, then the minimum of the range will
@@ -33,7 +35,7 @@
      *
      * @return the clamped value.
      */
-    public static float clamp(float value, int min, int max) {
+    public static float clamp(float value, float min, float max) {
         if (value < min) {
             return min;
         } else if (value > max) {
diff --git a/core-utils/java/android/support/v4/print/PrintHelper.java b/core-utils/java/android/support/v4/print/PrintHelper.java
index 87899e2..fb8bc12 100644
--- a/core-utils/java/android/support/v4/print/PrintHelper.java
+++ b/core-utils/java/android/support/v4/print/PrintHelper.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.print;
 
+import android.support.annotation.RequiresApi;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Build;
@@ -79,11 +80,8 @@
      * @return True if printing is supported.
      */
     public static boolean systemSupportsPrint() {
-        if (Build.VERSION.SDK_INT >= 19) {
-            // Supported on Android 4.4 or later.
-            return true;
-        }
-        return false;
+        // Supported on Android 4.4 or later.
+        return Build.VERSION.SDK_INT >= 19;
     }
 
     /**
@@ -154,6 +152,7 @@
     /**
      * Generic implementation for KitKat to Api24
      */
+    @RequiresApi(19)
     private static class PrintHelperImpl<RealHelper extends PrintHelperKitkat>
             implements PrintHelperVersionImpl {
         private final RealHelper mPrintHelper;
@@ -226,6 +225,7 @@
     /**
      * Implementation used on KitKat
      */
+    @RequiresApi(19)
     private static final class PrintHelperKitkatImpl extends PrintHelperImpl<PrintHelperKitkat> {
         PrintHelperKitkatImpl(Context context) {
             super(new PrintHelperKitkat(context));
@@ -235,6 +235,7 @@
     /**
      * Implementation used on Api20 to Api22
      */
+    @RequiresApi(20)
     private static final class PrintHelperApi20Impl extends PrintHelperImpl<PrintHelperApi20> {
         PrintHelperApi20Impl(Context context) {
             super(new PrintHelperApi20(context));
@@ -244,6 +245,7 @@
     /**
      * Implementation used on Api23
      */
+    @RequiresApi(23)
     private static final class PrintHelperApi23Impl extends PrintHelperImpl<PrintHelperApi23> {
         PrintHelperApi23Impl(Context context) {
             super(new PrintHelperApi23(context));
@@ -254,6 +256,7 @@
     /**
      * Implementation used on Api24 and above
      */
+    @RequiresApi(24)
     private static final class PrintHelperApi24Impl extends PrintHelperImpl<PrintHelperApi24> {
         PrintHelperApi24Impl(Context context) {
             super(new PrintHelperApi24(context));
@@ -267,17 +270,16 @@
      * @return the <code>PrintHelper</code> to support printing images.
      */
     public PrintHelper(Context context) {
-        if (systemSupportsPrint()) {
-            if (Build.VERSION.SDK_INT >= 24) {
-                mImpl = new PrintHelperApi24Impl(context);
-            } else if (Build.VERSION.SDK_INT >= 23) {
-                mImpl = new PrintHelperApi23Impl(context);
-            } else if (Build.VERSION.SDK_INT >= 20) {
-                mImpl = new PrintHelperApi20Impl(context);
-            } else {
-                mImpl = new PrintHelperKitkatImpl(context);
-            }
+        if (Build.VERSION.SDK_INT >= 24) {
+            mImpl = new PrintHelperApi24Impl(context);
+        } else if (Build.VERSION.SDK_INT >= 23) {
+            mImpl = new PrintHelperApi23Impl(context);
+        } else if (Build.VERSION.SDK_INT >= 20) {
+            mImpl = new PrintHelperApi20Impl(context);
+        } else if (Build.VERSION.SDK_INT >= 19){
+            mImpl = new PrintHelperKitkatImpl(context);
         } else {
+            // System does not support printing.
             mImpl = new PrintHelperStubImpl();
         }
     }
diff --git a/core-utils/java/android/support/v4/provider/DocumentFile.java b/core-utils/java/android/support/v4/provider/DocumentFile.java
index c573db0..2d1550d 100644
--- a/core-utils/java/android/support/v4/provider/DocumentFile.java
+++ b/core-utils/java/android/support/v4/provider/DocumentFile.java
@@ -107,8 +107,7 @@
      *            {@link Intent#ACTION_CREATE_DOCUMENT} request.
      */
     public static DocumentFile fromSingleUri(Context context, Uri singleUri) {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             return new SingleDocumentFile(null, context, singleUri);
         } else {
             return null;
@@ -125,8 +124,7 @@
      *            {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request.
      */
     public static DocumentFile fromTreeUri(Context context, Uri treeUri) {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 21) {
+        if (Build.VERSION.SDK_INT >= 21) {
             return new TreeDocumentFile(null, context,
                     DocumentsContractApi21.prepareTreeUri(treeUri));
         } else {
@@ -139,8 +137,7 @@
      * {@link android.provider.DocumentsProvider}.
      */
     public static boolean isDocumentUri(Context context, Uri uri) {
-        final int version = Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (Build.VERSION.SDK_INT >= 19) {
             return DocumentsContractApi19.isDocumentUri(context, uri);
         } else {
             return false;
diff --git a/core-utils/java/android/support/v4/provider/SingleDocumentFile.java b/core-utils/java/android/support/v4/provider/SingleDocumentFile.java
index 3a4ccf2..606c351 100644
--- a/core-utils/java/android/support/v4/provider/SingleDocumentFile.java
+++ b/core-utils/java/android/support/v4/provider/SingleDocumentFile.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.support.annotation.RequiresApi;
 import android.support.v4.provider.DocumentsContractApi19;
 
+@RequiresApi(19)
 class SingleDocumentFile extends DocumentFile {
     private Context mContext;
     private Uri mUri;
diff --git a/core-utils/java/android/support/v4/provider/TreeDocumentFile.java b/core-utils/java/android/support/v4/provider/TreeDocumentFile.java
index 02975bd..cb8979d 100644
--- a/core-utils/java/android/support/v4/provider/TreeDocumentFile.java
+++ b/core-utils/java/android/support/v4/provider/TreeDocumentFile.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.support.annotation.RequiresApi;
 
+@RequiresApi(21)
 class TreeDocumentFile extends DocumentFile {
     private Context mContext;
     private Uri mUri;
diff --git a/customtabs/tests/src/android/support/customtabs/PostMessageServiceConnectionTest.java b/customtabs/tests/src/android/support/customtabs/PostMessageServiceConnectionTest.java
index a2b1b31..c0fadae 100644
--- a/customtabs/tests/src/android/support/customtabs/PostMessageServiceConnectionTest.java
+++ b/customtabs/tests/src/android/support/customtabs/PostMessageServiceConnectionTest.java
@@ -61,6 +61,7 @@
         mContext = mActivityTestRule.getActivity();
         mConnection = new PostMessageServiceConnection(
                 new CustomTabsSessionToken(mCallback.getStub())) {
+            @Override
             public void onPostMessageServiceConnected() {
                 mServiceConnected = true;
             }
diff --git a/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java b/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
index d7c258f..df0df85 100644
--- a/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
+++ b/design/lollipop/android/support/design/widget/FloatingActionButtonLollipop.java
@@ -80,8 +80,7 @@
 
     @Override
     void onElevationsChanged(final float elevation, final float pressedTranslationZ) {
-        final int sdk = Build.VERSION.SDK_INT;
-        if (sdk == 21) {
+        if (Build.VERSION.SDK_INT == 21) {
             // Animations produce NPE in version 21. Bluntly set the values instead (matching the
             // logic in the animations below).
             if (mView.isEnabled()) {
diff --git a/design/src/android/support/design/internal/BaselineLayout.java b/design/src/android/support/design/internal/BaselineLayout.java
index d2a7be4..0bfdf24 100644
--- a/design/src/android/support/design/internal/BaselineLayout.java
+++ b/design/src/android/support/design/internal/BaselineLayout.java
@@ -42,6 +42,7 @@
         super(context, attrs, defStyleAttr);
     }
 
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int count = getChildCount();
         int maxWidth = 0;
diff --git a/design/src/android/support/design/internal/ForegroundLinearLayout.java b/design/src/android/support/design/internal/ForegroundLinearLayout.java
index bda83dd..6d90503 100644
--- a/design/src/android/support/design/internal/ForegroundLinearLayout.java
+++ b/design/src/android/support/design/internal/ForegroundLinearLayout.java
@@ -83,6 +83,7 @@
      * @return foreground gravity.
      * @see #setForegroundGravity(int)
      */
+    @Override
     public int getForegroundGravity() {
         return mForegroundGravity;
     }
@@ -93,6 +94,7 @@
      * @param foregroundGravity See {@link android.view.Gravity}
      * @see #getForegroundGravity()
      */
+    @Override
     public void setForegroundGravity(int foregroundGravity) {
         if (mForegroundGravity != foregroundGravity) {
             if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
@@ -144,6 +146,7 @@
      *
      * @param drawable The Drawable to be drawn on top of the children.
      */
+    @Override
     public void setForeground(Drawable drawable) {
         if (mForeground != drawable) {
             if (mForeground != null) {
@@ -177,6 +180,7 @@
      *
      * @return A Drawable or null if no foreground was set.
      */
+    @Override
     public Drawable getForeground() {
         return mForeground;
     }
diff --git a/design/src/android/support/design/widget/FloatingActionButton.java b/design/src/android/support/design/widget/FloatingActionButton.java
index 2ac0785..b938836 100644
--- a/design/src/android/support/design/widget/FloatingActionButton.java
+++ b/design/src/android/support/design/widget/FloatingActionButton.java
@@ -248,6 +248,7 @@
      *
      * @param tint the tint to apply, may be {@code null} to clear tint
      */
+    @Override
     public void setBackgroundTintList(@Nullable ColorStateList tint) {
         if (mBackgroundTint != tint) {
             mBackgroundTint = tint;
@@ -277,6 +278,7 @@
      * @param tintMode the blending mode used to apply the tint, may be
      *                 {@code null} to clear tint
      */
+    @Override
     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
         if (mBackgroundTintMode != tintMode) {
             mBackgroundTintMode = tintMode;
diff --git a/design/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java b/design/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java
index aeca0be..1dcb592 100644
--- a/design/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java
+++ b/design/tests/src/android/support/design/widget/AppBarWithCollapsingToolbarTest.java
@@ -26,7 +26,6 @@
 import android.support.design.test.R;
 import android.support.test.filters.FlakyTest;
 import android.support.test.filters.LargeTest;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.Suppress;
 import android.widget.ImageView;
 
@@ -536,7 +535,6 @@
     @Suppress
     @FlakyTest(bugId = 30701044)
     @Test
-    @SdkSuppress(minSdkVersion = 11)
     public void testPinnedToolbarWithMargins() throws Throwable {
         configureContent(R.layout.design_appbar_toolbar_collapse_pin_margins,
                 R.string.design_appbar_collapsing_toolbar_pin_margins);
diff --git a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java b/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
index 73ad193..a273be2 100644
--- a/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
+++ b/design/tests/src/android/support/design/widget/CoordinatorLayoutTest.java
@@ -37,6 +37,7 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.annotation.TargetApi;
 import android.app.Instrumentation;
 import android.graphics.Rect;
 import android.support.design.test.R;
@@ -76,6 +77,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 21)
+    @TargetApi(21)
     public void testSetFitSystemWindows() throws Throwable {
         final Instrumentation instrumentation = getInstrumentation();
         final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout;
diff --git a/design/tests/src/android/support/design/widget/NavigationViewTest.java b/design/tests/src/android/support/design/widget/NavigationViewTest.java
index 8d6746d..e7e922a 100755
--- a/design/tests/src/android/support/design/widget/NavigationViewTest.java
+++ b/design/tests/src/android/support/design/widget/NavigationViewTest.java
@@ -61,6 +61,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.annotation.TargetApi;
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Parcelable;
@@ -406,6 +407,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 11)
+    @TargetApi(11)
     @Test
     public void testHeaderState() {
         // Open our drawer
@@ -445,6 +447,7 @@
     }
 
     @SdkSuppress(minSdkVersion = 11)
+    @TargetApi(11)
     @Test
     public void testActionViewState() {
         // Open our drawer
diff --git a/dynamic-animation/src/android/support/animation/DynamicAnimation.java b/dynamic-animation/src/android/support/animation/DynamicAnimation.java
index bd0f853..ee90df2 100644
--- a/dynamic-animation/src/android/support/animation/DynamicAnimation.java
+++ b/dynamic-animation/src/android/support/animation/DynamicAnimation.java
@@ -18,6 +18,7 @@
 
 import android.os.Build;
 import android.os.Looper;
+import android.support.v4.view.ViewCompat;
 import android.util.AndroidRuntimeException;
 import android.view.View;
 
@@ -89,18 +90,12 @@
     public static final ViewProperty TRANSLATION_Z = new ViewProperty("translationZ") {
         @Override
         void setValue(View view, float value) {
-            if (isZSupported()) {
-                view.setTranslationZ(value);
-            }
+            ViewCompat.setTranslationZ(view, value);
         }
 
         @Override
         float getValue(View view) {
-            if (isZSupported()) {
-                return view.getTranslationZ();
-            } else {
-                return 0;
-            }
+            return ViewCompat.getTranslationZ(view);
         }
     };
 
@@ -215,18 +210,12 @@
     public static final ViewProperty Z = new ViewProperty("z") {
         @Override
         void setValue(View view, float value) {
-            if (isZSupported()) {
-                view.setZ(value);
-            }
+            ViewCompat.setZ(view, value);
         }
 
         @Override
         float getValue(View view) {
-            if (isZSupported()) {
-                return view.getZ();
-            } else {
-                return 0;
-            }
+            return ViewCompat.getZ(view);
         }
     };
 
@@ -617,13 +606,6 @@
     }
 
     /**
-     * Returns whether z and translationZ are supported on the current build version.
-     */
-    private static boolean isZSupported() {
-        return Build.VERSION.SDK_INT >= 21;
-    }
-
-    /**
      * Updates the property value through the corresponding setter.
      */
     void setPropertyValue(float value) {
diff --git a/exifinterface/src/android/support/media/ExifInterface.java b/exifinterface/src/android/support/media/ExifInterface.java
index 4ae0312..c4d602d 100644
--- a/exifinterface/src/android/support/media/ExifInterface.java
+++ b/exifinterface/src/android/support/media/ExifInterface.java
@@ -3614,6 +3614,7 @@
             return skipped;
         }
 
+        @Override
         public int readUnsignedShort() throws IOException {
             mPosition += 2;
             if (mPosition > mLength) {
@@ -3692,10 +3693,12 @@
             mByteOrder = byteOrder;
         }
 
+        @Override
         public void write(byte[] bytes) throws IOException {
             mOutputStream.write(bytes);
         }
 
+        @Override
         public void write(byte[] bytes, int offset, int length) throws IOException {
             mOutputStream.write(bytes, offset, length);
         }
diff --git a/fragment/java/android/support/v4/app/FragmentActivity.java b/fragment/java/android/support/v4/app/FragmentActivity.java
index 2b30b5c..bfb06db 100644
--- a/fragment/java/android/support/v4/app/FragmentActivity.java
+++ b/fragment/java/android/support/v4/app/FragmentActivity.java
@@ -248,6 +248,7 @@
      *
      * @param isInMultiWindowMode True if the activity is in multi-window mode.
      */
+    @Override
     @CallSuper
     public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
         mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode);
@@ -262,6 +263,7 @@
      *
      * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
      */
+    @Override
     @CallSuper
     public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
         mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
@@ -429,6 +431,7 @@
     /**
      * Hook in to note that fragment state is no longer saved.
      */
+    @Override
     public void onStateNotSaved() {
         mFragments.noteStateNotSaved();
     }
@@ -631,6 +634,7 @@
      * closed for you after you return.
      * @param args additional arguments to the dump request.
      */
+    @Override
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
         super.dump(prefix, fd, writer, args);
         writer.print(prefix); writer.print("Local FragmentActivity ");
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index 7e448df..0d311c0 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -3149,10 +3149,12 @@
         mPrimaryNav = f;
     }
 
+    @Override
     public Fragment getPrimaryNavigationFragment() {
         return mPrimaryNav;
     }
 
+    @Override
     public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
             boolean recursive) {
         if (mLifecycleCallbacks == null) {
@@ -3161,6 +3163,7 @@
         mLifecycleCallbacks.add(new Pair(cb, recursive));
     }
 
+    @Override
     public void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb) {
         if (mLifecycleCallbacks == null) {
             return;
diff --git a/fragment/java/android/support/v4/app/FragmentTransition.java b/fragment/java/android/support/v4/app/FragmentTransition.java
index 27cca90..fb3ad12 100644
--- a/fragment/java/android/support/v4/app/FragmentTransition.java
+++ b/fragment/java/android/support/v4/app/FragmentTransition.java
@@ -17,6 +17,7 @@
 
 import android.graphics.Rect;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.support.v4.util.ArrayMap;
 import android.support.v4.view.ViewCompat;
 import android.util.SparseArray;
@@ -82,38 +83,41 @@
     static void startTransitions(FragmentManagerImpl fragmentManager,
             ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop,
             int startIndex, int endIndex, boolean isOptimized) {
-        if (fragmentManager.mCurState < Fragment.CREATED
-                || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+        if (fragmentManager.mCurState < Fragment.CREATED) {
             return;
         }
-        SparseArray<FragmentContainerTransition> transitioningFragments =
-                new SparseArray<>();
-        for (int i = startIndex; i < endIndex; i++) {
-            final BackStackRecord record = records.get(i);
-            final boolean isPop = isRecordPop.get(i);
-            if (isPop) {
-                calculatePopFragments(record, transitioningFragments, isOptimized);
-            } else {
-                calculateFragments(record, transitioningFragments, isOptimized);
-            }
-        }
 
-        if (transitioningFragments.size() != 0) {
-            final View nonExistentView = new View(fragmentManager.mHost.getContext());
-            final int numContainers = transitioningFragments.size();
-            for (int i = 0; i < numContainers; i++) {
-                int containerId = transitioningFragments.keyAt(i);
-                ArrayMap<String, String> nameOverrides = calculateNameOverrides(containerId,
-                        records, isRecordPop, startIndex, endIndex);
-
-                FragmentContainerTransition containerTransition = transitioningFragments.valueAt(i);
-
-                if (isOptimized) {
-                    configureTransitionsOptimized(fragmentManager, containerId,
-                            containerTransition, nonExistentView, nameOverrides);
+        if (Build.VERSION.SDK_INT >= 21) {
+            SparseArray<FragmentContainerTransition> transitioningFragments =
+                    new SparseArray<>();
+            for (int i = startIndex; i < endIndex; i++) {
+                final BackStackRecord record = records.get(i);
+                final boolean isPop = isRecordPop.get(i);
+                if (isPop) {
+                    calculatePopFragments(record, transitioningFragments, isOptimized);
                 } else {
-                    configureTransitionsUnoptimized(fragmentManager, containerId,
-                            containerTransition, nonExistentView, nameOverrides);
+                    calculateFragments(record, transitioningFragments, isOptimized);
+                }
+            }
+
+            if (transitioningFragments.size() != 0) {
+                final View nonExistentView = new View(fragmentManager.mHost.getContext());
+                final int numContainers = transitioningFragments.size();
+                for (int i = 0; i < numContainers; i++) {
+                    int containerId = transitioningFragments.keyAt(i);
+                    ArrayMap<String, String> nameOverrides = calculateNameOverrides(containerId,
+                            records, isRecordPop, startIndex, endIndex);
+
+                    FragmentContainerTransition containerTransition =
+                            transitioningFragments.valueAt(i);
+
+                    if (isOptimized) {
+                        configureTransitionsOptimized(fragmentManager, containerId,
+                                containerTransition, nonExistentView, nameOverrides);
+                    } else {
+                        configureTransitionsUnoptimized(fragmentManager, containerId,
+                                containerTransition, nonExistentView, nameOverrides);
+                    }
                 }
             }
         }
@@ -185,6 +189,7 @@
      *                      the final fragment's Views as given in
      *                      {@link FragmentTransaction#addSharedElement(View, String)}.
      */
+    @RequiresApi(21)
     private static void configureTransitionsOptimized(FragmentManagerImpl fragmentManager,
             int containerId, FragmentContainerTransition fragments,
             View nonExistentView, ArrayMap<String, String> nameOverrides) {
@@ -246,6 +251,7 @@
      * the entire fragment's view GONE, make each exiting view INVISIBLE. At the end of the
      * transition, make the fragment's view GONE.
      */
+    @RequiresApi(21)
     private static void replaceHide(Object exitTransition, Fragment exitingFragment,
             final ArrayList<View> exitingViews) {
         if (exitingFragment != null && exitTransition != null && exitingFragment.mAdded
@@ -278,6 +284,7 @@
      *                      the final fragment's Views as given in
      *                      {@link FragmentTransaction#addSharedElement(View, String)}.
      */
+    @RequiresApi(21)
     private static void configureTransitionsUnoptimized(FragmentManagerImpl fragmentManager,
             int containerId, FragmentContainerTransition fragments,
             View nonExistentView, ArrayMap<String, String> nameOverrides) {
@@ -355,6 +362,7 @@
      * @param exitTransition The exit transition of the outgoing fragment
      * @param exitingViews The exiting views of the outgoing fragment
      */
+    @RequiresApi(21)
     private static void scheduleTargetChange(final ViewGroup sceneRoot,
             final Fragment inFragment, final View nonExistentView,
             final ArrayList<View> sharedElementsIn,
@@ -397,6 +405,7 @@
      * @return A TransitionSet wrapping the shared element transition or null if no such transition
      * exists.
      */
+    @RequiresApi(21)
     private static Object getSharedElementTransition(Fragment inFragment,
             Fragment outFragment, boolean isPop) {
         if (inFragment == null || outFragment == null) {
@@ -411,6 +420,7 @@
     /**
      * Returns a clone of the enter transition or null if no such transition exists.
      */
+    @RequiresApi(21)
     private static Object getEnterTransition(Fragment inFragment, boolean isPop) {
         if (inFragment == null) {
             return null;
@@ -423,6 +433,7 @@
     /**
      * Returns a clone of the exit transition or null if no such transition exists.
      */
+    @RequiresApi(21)
     private static Object getExitTransition(Fragment outFragment, boolean isPop) {
         if (outFragment == null) {
             return null;
@@ -459,6 +470,7 @@
      *                       epicenter
      * @return The shared element transition or null if no shared elements exist
      */
+    @RequiresApi(21)
     private static Object configureSharedElementsOptimized(final ViewGroup sceneRoot,
             final View nonExistentView, final ArrayMap<String, String> nameOverrides,
             final FragmentContainerTransition fragments,
@@ -587,6 +599,7 @@
      *                       epicenter
      * @return The shared element transition or null if no shared elements exist
      */
+    @RequiresApi(21)
     private static Object configureSharedElementsUnoptimized(final ViewGroup sceneRoot,
             final View nonExistentView, final ArrayMap<String, String> nameOverrides,
             final FragmentContainerTransition fragments,
@@ -683,6 +696,7 @@
      * @return The mapping of shared element names to the Views in the hierarchy or null
      * if there is no shared element transition.
      */
+    @RequiresApi(21)
     private static ArrayMap<String, View> captureOutSharedElements(
             ArrayMap<String, String> nameOverrides, Object sharedElementTransition,
             FragmentContainerTransition fragments) {
@@ -738,6 +752,7 @@
      * @return The mapping of shared element names to the Views in the hierarchy or null
      * if there is no shared element transition.
      */
+    @RequiresApi(21)
     private static ArrayMap<String, View> captureInSharedElements(
             ArrayMap<String, String> nameOverrides, Object sharedElementTransition,
             FragmentContainerTransition fragments) {
@@ -833,6 +848,7 @@
      * @param outIsPop Is the outgoing fragment being removed as a pop transaction?
      * @param outTransaction The transaction that caused the fragment to be removed.
      */
+    @RequiresApi(21)
     private static void setOutEpicenter(Object sharedElementTransition,
             Object exitTransition, ArrayMap<String, View> outSharedElements, boolean outIsPop,
             BackStackRecord outTransaction) {
@@ -897,6 +913,7 @@
         }
     }
 
+    @RequiresApi(21)
     private static ArrayList<View> configureEnteringExitingViews(Object transition,
             Fragment fragment, ArrayList<View> sharedElements, View nonExistentView) {
         ArrayList<View> viewList = null;
@@ -934,6 +951,7 @@
      * Merges exit, shared element, and enter transitions so that they act together or
      * sequentially as defined in the fragments.
      */
+    @RequiresApi(21)
     private static Object mergeTransitions(Object enterTransition,
             Object exitTransition, Object sharedElementTransition, Fragment inFragment,
             boolean isPop) {
diff --git a/fragment/tests/java/android/support/v4/app/FragmentReplaceTest.java b/fragment/tests/java/android/support/v4/app/FragmentReplaceTest.java
index 6aadeb7..fe7045c 100644
--- a/fragment/tests/java/android/support/v4/app/FragmentReplaceTest.java
+++ b/fragment/tests/java/android/support/v4/app/FragmentReplaceTest.java
@@ -26,7 +26,6 @@
 import android.support.fragment.test.R;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
-import android.support.test.filters.SdkSuppress;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.app.test.FragmentTestActivity;
@@ -98,7 +97,6 @@
         });
     }
 
-    @SdkSuppress(minSdkVersion = 11)
     @Test
     public void testBackPressWithFrameworkFragment() throws Throwable {
         final Activity activity = mActivityRule.getActivity();
diff --git a/fragment/tests/java/android/support/v4/app/NestedFragmentTest.java b/fragment/tests/java/android/support/v4/app/NestedFragmentTest.java
index 39e19be..4d63c27 100644
--- a/fragment/tests/java/android/support/v4/app/NestedFragmentTest.java
+++ b/fragment/tests/java/android/support/v4/app/NestedFragmentTest.java
@@ -60,6 +60,7 @@
         fragmentManager.beginTransaction().add(mParentFragment, "parent").commit();
         final CountDownLatch latch = new CountDownLatch(1);
         mActivityRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 fragmentManager.executePendingTransactions();
                 latch.countDown();
@@ -89,6 +90,7 @@
 
         final CountDownLatch latch = new CountDownLatch(1);
         mActivityRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mParentFragment.getChildFragment().startActivityForResult(
                         new Intent(Intent.ACTION_CALL),
diff --git a/gradlew b/gradlew
index 014f353..98b9f82 100755
--- a/gradlew
+++ b/gradlew
@@ -62,7 +62,7 @@
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Pick the correct fullsdk for this OS.
-if [ "$os" = "Darwin" ]; then
+if [ darwin ]; then
     plat="darwin"
 else
     plat="linux"
diff --git a/graphics/drawable/animated/src/android/support/graphics/drawable/Animatable2Compat.java b/graphics/drawable/animated/src/android/support/graphics/drawable/Animatable2Compat.java
new file mode 100644
index 0000000..d9d0f36
--- /dev/null
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/Animatable2Compat.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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.graphics.drawable;
+
+import static android.os.Build.VERSION_CODES.M;
+
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+
+/**
+ * Abstract class that drawables supporting animations and callbacks should extend in support lib.
+ */
+public interface Animatable2Compat extends Animatable {
+
+    /**
+     * Adds a callback to listen to the animation events.
+     *
+     * @param callback Callback to add.
+     */
+    void registerAnimationCallback(@NonNull AnimationCallback callback);
+
+    /**
+     * Removes the specified animation callback.
+     *
+     * @param callback Callback to remove.
+     * @return {@code false} if callback didn't exist in the call back list, or {@code true} if
+     *         callback has been removed successfully.
+     */
+    boolean unregisterAnimationCallback(@NonNull AnimationCallback callback);
+
+    /**
+     * Removes all existing animation callbacks.
+     */
+    void clearAnimationCallbacks();
+
+    /**
+     * Animation callback interface. Used to notify animation events.
+     */
+    abstract class AnimationCallback {
+        /**
+         * Called when the animation starts.
+         *
+         * @param drawable The drawable started the animation.
+         */
+        public void onAnimationStart(Drawable drawable) {};
+        /**
+         * Called when the animation ends.
+         *
+         * @param drawable The drawable finished the animation.
+         */
+        public void onAnimationEnd(Drawable drawable) {};
+
+        // Only when passing this Animatable2Compat.AnimationCallback to a frameworks' AVD, we need
+        // to bridge this compat version callback with the frameworks' callback.
+        Animatable2.AnimationCallback mPlatformCallback;
+
+        @RequiresApi(M)
+        Animatable2.AnimationCallback getPlatformCallback() {
+            if (mPlatformCallback == null) {
+                mPlatformCallback = new Animatable2.AnimationCallback() {
+                    @Override
+                    public void onAnimationStart(Drawable drawable) {
+                        AnimationCallback.this.onAnimationStart(drawable);
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        AnimationCallback.this.onAnimationEnd(drawable);
+                    }
+                };
+            }
+            return mPlatformCallback;
+        }
+    }
+}
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 33ff2c5..1a7b51e 100644
--- a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
@@ -16,6 +16,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
@@ -51,7 +52,8 @@
 import java.util.List;
 
 /**
- * For API 24 and above, this class is delegating to the framework's {@link AnimatedVectorDrawable}.
+ * For API 24 and above, this class is delegating to the framework's {@link
+ * AnimatedVectorDrawable}.
  * For older API version, this class uses {@link android.animation.ObjectAnimator} and
  * {@link android.animation.AnimatorSet} to animate the properties of a
  * {@link VectorDrawableCompat} to create an animated drawable.
@@ -132,7 +134,8 @@
  * </ul>
  */
 @SuppressLint("NewApi")
-public class AnimatedVectorDrawableCompat extends VectorDrawableCommon implements Animatable {
+public class AnimatedVectorDrawableCompat extends VectorDrawableCommon
+        implements Animatable2Compat {
     private static final String LOGTAG = "AnimatedVDCompat";
 
     private static final String ANIMATED_VECTOR = "animated-vector";
@@ -148,6 +151,13 @@
 
     AnimatedVectorDrawableDelegateState mCachedConstantStateDelegate;
 
+    // Use internal listener to support AVDC's callback.
+    private Animator.AnimatorListener mAnimatorListener = null;
+
+    // Use an array to keep track of multiple call back associated with one drawable.
+    private ArrayList<Animatable2Compat.AnimationCallback> mAnimationCallbacks = null;
+
+
     AnimatedVectorDrawableCompat() {
         this(null, null, null);
     }
@@ -157,8 +167,8 @@
     }
 
     private AnimatedVectorDrawableCompat(@Nullable Context context,
-                                         @Nullable AnimatedVectorDrawableCompatState state,
-                                         @Nullable Resources res) {
+            @Nullable AnimatedVectorDrawableCompatState state,
+            @Nullable Resources res) {
         mContext = context;
         if (state != null) {
             mAnimatedVectorState = state;
@@ -192,7 +202,7 @@
      */
     @Nullable
     public static AnimatedVectorDrawableCompat create(@NonNull Context context,
-                                                      @DrawableRes int resId) {
+            @DrawableRes int resId) {
         if (Build.VERSION.SDK_INT >= 24) {
             final AnimatedVectorDrawableCompat drawable = new AnimatedVectorDrawableCompat(context);
             drawable.mDelegateDrawable = ResourcesCompat.getDrawable(context.getResources(), resId,
@@ -269,7 +279,7 @@
             return;
         }
         mAnimatedVectorState.mVectorDrawable.draw(canvas);
-        if (isStarted()) {
+        if (mAnimatedVectorState.mAnimatorSet.isStarted()) {
             invalidateSelf();
         }
     }
@@ -474,9 +484,10 @@
                     a.recycle();
                 }
             }
-
             eventType = parser.next();
         }
+
+        mAnimatedVectorState.setupAnimatorSet();
     }
 
     @Override
@@ -557,7 +568,9 @@
     private static class AnimatedVectorDrawableCompatState extends ConstantState {
         int mChangingConfigurations;
         VectorDrawableCompat mVectorDrawable;
-        ArrayList<Animator> mAnimators;
+        // Combining the array of Animators into a single AnimatorSet to hook up listener easier.
+        AnimatorSet mAnimatorSet;
+        private ArrayList<Animator> mAnimators;
         ArrayMap<Animator, String> mTargetNameMap;
 
         public AnimatedVectorDrawableCompatState(Context context,
@@ -589,6 +602,7 @@
                         mAnimators.add(animClone);
                         mTargetNameMap.put(animClone, targetName);
                     }
+                    setupAnimatorSet();
                 }
             }
         }
@@ -607,6 +621,13 @@
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
+
+        public void setupAnimatorSet() {
+            if (mAnimatorSet == null) {
+                mAnimatorSet = new AnimatorSet();
+            }
+            mAnimatorSet.playTogether(mAnimators);
+        }
     }
 
     /**
@@ -657,30 +678,7 @@
         if (mDelegateDrawable != null) {
             return ((AnimatedVectorDrawable) mDelegateDrawable).isRunning();
         }
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            if (animator.isRunning()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean isStarted() {
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        if (animators == null) {
-            return false;
-        }
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            if (animator.isRunning()) {
-                return true;
-            }
-        }
-        return false;
+        return mAnimatedVectorState.mAnimatorSet.isRunning();
     }
 
     @Override
@@ -690,16 +688,11 @@
             return;
         }
         // If any one of the animator has not ended, do nothing.
-        if (isStarted()) {
+        if (mAnimatedVectorState.mAnimatorSet.isStarted()) {
             return;
         }
-        // Otherwise, kick off every animator.
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            animator.start();
-        }
+        // Otherwise, kick off animatorSet.
+        mAnimatedVectorState.mAnimatorSet.start();
         invalidateSelf();
     }
 
@@ -709,12 +702,7 @@
             ((AnimatedVectorDrawable) mDelegateDrawable).stop();
             return;
         }
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            animator.end();
-        }
+        mAnimatedVectorState.mAnimatorSet.end();
     }
 
     final Callback mCallback = new Callback() {
@@ -733,4 +721,180 @@
             unscheduleSelf(what);
         }
     };
+
+    /**
+     * A helper function to unregister the Animatable2Compat callback from the platform's
+     * Animatable2 callback, while keeping the internal array of callback up to date.
+     */
+    private static boolean unregisterPlatformCallback(AnimatedVectorDrawable dr,
+            Animatable2Compat.AnimationCallback callback) {
+        return dr.unregisterAnimationCallback(callback.getPlatformCallback());
+    }
+
+    @Override
+    public void registerAnimationCallback(@NonNull Animatable2Compat.AnimationCallback
+            callback) {
+        if (mDelegateDrawable != null) {
+            registerPlatformCallback((AnimatedVectorDrawable) mDelegateDrawable, callback);
+            return;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        // Add listener accordingly.
+        if (mAnimationCallbacks == null) {
+            mAnimationCallbacks = new ArrayList<>();
+        }
+
+        if (mAnimationCallbacks.contains(callback)) {
+            // If this call back is already in, then don't need to append another copy.
+            return;
+        }
+
+        mAnimationCallbacks.add(callback);
+
+        if (mAnimatorListener == null) {
+            // Create a animator listener and trigger the callback events when listener is
+            // triggered.
+            mAnimatorListener = new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    ArrayList<Animatable2Compat.AnimationCallback> tmpCallbacks =
+                            new ArrayList<>(mAnimationCallbacks);
+                    int size = tmpCallbacks.size();
+                    for (int i = 0; i < size; i++) {
+                        tmpCallbacks.get(i).onAnimationStart(AnimatedVectorDrawableCompat.this);
+                    }
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    ArrayList<Animatable2Compat.AnimationCallback> tmpCallbacks =
+                            new ArrayList<>(mAnimationCallbacks);
+                    int size = tmpCallbacks.size();
+                    for (int i = 0; i < size; i++) {
+                        tmpCallbacks.get(i).onAnimationEnd(AnimatedVectorDrawableCompat.this);
+                    }
+                }
+            };
+        }
+        mAnimatedVectorState.mAnimatorSet.addListener(mAnimatorListener);
+    }
+
+    /**
+     * A helper function to register the Animatable2Compat callback on the platform's Animatable2
+     * callback.
+     */
+    private static void registerPlatformCallback(@NonNull AnimatedVectorDrawable avd,
+            @NonNull final Animatable2Compat.AnimationCallback callback) {
+        avd.registerAnimationCallback(callback.getPlatformCallback());
+    }
+
+    /**
+     * A helper function to clean up the animator listener in the mAnimatorSet.
+     */
+    private void removeAnimatorSetListener() {
+        if (mAnimatorListener != null) {
+            mAnimatedVectorState.mAnimatorSet.removeListener(mAnimatorListener);
+            mAnimatorListener = null;
+        }
+    }
+
+    @Override
+    public boolean unregisterAnimationCallback(
+            @NonNull Animatable2Compat.AnimationCallback callback) {
+        if (mDelegateDrawable != null) {
+            unregisterPlatformCallback((AnimatedVectorDrawable) mDelegateDrawable, callback);
+        }
+
+        if (mAnimationCallbacks == null || callback == null) {
+            // Nothing to be removed.
+            return false;
+        }
+        boolean removed = mAnimationCallbacks.remove(callback);
+
+        //  When the last call back unregistered, remove the listener accordingly.
+        if (mAnimationCallbacks.size() == 0) {
+            removeAnimatorSetListener();
+        }
+        return removed;
+    }
+
+    @Override
+    public void clearAnimationCallbacks() {
+        if (mDelegateDrawable != null) {
+            ((AnimatedVectorDrawable) mDelegateDrawable).clearAnimationCallbacks();
+            return;
+        }
+        removeAnimatorSetListener();
+        if (mAnimationCallbacks == null) {
+            return;
+        }
+
+        mAnimationCallbacks.clear();
+    }
+
+    /**
+     * Utility function to register callback to Drawable, when the drawable is created from XML and
+     * referred in Java code, e.g: ImageView.getDrawable().
+     * From API 24 on, the drawable is treated as an AnimatedVectorDrawable.
+     * Otherwise, it is treated as AnimatedVectorDrawableCompat.
+     */
+    public static void registerAnimationCallback(Drawable dr,
+            Animatable2Compat.AnimationCallback callback) {
+        if (dr == null || callback == null) {
+            return;
+        }
+        if (!(dr instanceof Animatable)) {
+            return;
+        }
+
+        if (Build.VERSION.SDK_INT >= 24) {
+            registerPlatformCallback((AnimatedVectorDrawable) dr, callback);
+        } else {
+            ((AnimatedVectorDrawableCompat) dr).registerAnimationCallback(callback);
+        }
+    }
+
+    /**
+     * Utility function to unregister animation callback from Drawable, when the drawable is
+     * created from XML and referred in Java code, e.g: ImageView.getDrawable().
+     * From API 24 on, the drawable is treated as an AnimatedVectorDrawable.
+     * Otherwise, it is treated as AnimatedVectorDrawableCompat.
+     */
+    public static boolean unregisterAnimationCallback(Drawable dr,
+            Animatable2Compat.AnimationCallback callback) {
+        if (dr == null || callback == null) {
+            return false;
+        }
+        if (!(dr instanceof Animatable)) {
+            return false;
+        }
+
+        if (Build.VERSION.SDK_INT >= 24) {
+            return unregisterPlatformCallback((AnimatedVectorDrawable) dr, callback);
+        } else {
+            return ((AnimatedVectorDrawableCompat) dr).unregisterAnimationCallback(callback);
+        }
+    }
+
+    /**
+     * Utility function to clear animation callbacks from Drawable, when the drawable is
+     * created from XML and referred in Java code, e.g: ImageView.getDrawable().
+     * From API 24 on, the drawable is treated as an AnimatedVectorDrawable.
+     * Otherwise, it is treated as AnimatedVectorDrawableCompat.
+     */
+    public static void clearAnimationCallbacks(Drawable dr) {
+        if (dr == null || !(dr instanceof Animatable)) {
+            return;
+        }
+        if (Build.VERSION.SDK_INT >= 24) {
+            ((AnimatedVectorDrawable) dr).clearAnimationCallbacks();
+        } else {
+            ((AnimatedVectorDrawableCompat) dr).clearAnimationCallbacks();
+        }
+
+    }
 }
diff --git a/graphics/drawable/animated/tests/src/android/support/graphics/drawable/tests/AnimatedVectorDrawableTest.java b/graphics/drawable/animated/tests/src/android/support/graphics/drawable/tests/AnimatedVectorDrawableTest.java
index 5b44b2a..7cae5e8 100644
--- a/graphics/drawable/animated/tests/src/android/support/graphics/drawable/tests/AnimatedVectorDrawableTest.java
+++ b/graphics/drawable/animated/tests/src/android/support/graphics/drawable/tests/AnimatedVectorDrawableTest.java
@@ -17,6 +17,7 @@
 package android.support.graphics.drawable.tests;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -28,8 +29,10 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable.ConstantState;
 import android.support.annotation.DrawableRes;
+import android.support.graphics.drawable.Animatable2Compat;
 import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
 import android.support.graphics.drawable.animated.test.R;
 import android.support.test.InstrumentationRegistry;
@@ -69,8 +72,9 @@
 
     private static final int IMAGE_WIDTH = 64;
     private static final int IMAGE_HEIGHT = 64;
-    private static final @DrawableRes int DRAWABLE_RES_ID =
-            R.drawable.animation_vector_drawable_grouping_1;
+
+    @DrawableRes
+    private static final int DRAWABLE_RES_ID = R.drawable.animation_vector_drawable_grouping_1;
 
     private Context mContext;
     private Resources mResources;
@@ -79,6 +83,26 @@
     private Canvas mCanvas;
     private static final boolean DBG_DUMP_PNG = false;
 
+    // States to check for animation callback tests.
+    private boolean mAnimationStarted = false;
+    private boolean mAnimationEnded = false;
+
+    // Animation callback used for all callback related tests.
+    private Animatable2Compat.AnimationCallback mAnimationCallback =
+            new Animatable2Compat.AnimationCallback() {
+                @Override
+                public void onAnimationStart(
+                        Drawable drawable) {
+                    mAnimationStarted = true;
+                }
+
+                @Override
+                public void onAnimationEnd(
+                        Drawable drawable) {
+                    mAnimationEnded = true;
+                }
+            };
+
     public AnimatedVectorDrawableTest() {
         mActivityTestRule = new ActivityTestRule<>(DrawableStubActivity.class);
     }
@@ -389,4 +413,81 @@
             assertEquals(d1.mutate(), d1);
         }
     }
+
+    /**
+     * A helper function to setup the AVDC for callback tests.
+     */
+    private AnimatedVectorDrawableCompat setupAnimatedVectorDrawableCompat() {
+        final ImageButton imageButton =
+                (ImageButton) mActivityTestRule.getActivity().findViewById(R.id.imageButton);
+        mAnimationStarted = false;
+        mAnimationEnded = false;
+
+        AnimatedVectorDrawableCompat avd = AnimatedVectorDrawableCompat.create(mContext,
+                R.drawable.animation_vector_drawable_grouping_1); // Duration is 50 ms.
+        ViewCompat.setBackground(imageButton, avd);
+        return avd;
+    }
+
+    @Test
+    /**
+     * Test show that callback is successfully registered.
+     * Note that this test requires screen is on.
+     */
+    public void testRegisterCallback() throws Throwable {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                AnimatedVectorDrawableCompat avd = setupAnimatedVectorDrawableCompat();
+                avd.registerAnimationCallback(mAnimationCallback);
+                avd.start();
+            }
+        });
+        Thread.sleep(500);
+        assertTrue(mAnimationStarted);
+        assertTrue(mAnimationEnded);
+    }
+
+    @Test
+    /**
+     * Test show that callback is successfully removed.
+     * Note that this test requires screen is on.
+     */
+    public void testClearCallback() throws Throwable {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                AnimatedVectorDrawableCompat avd =
+                        setupAnimatedVectorDrawableCompat();
+                avd.registerAnimationCallback(mAnimationCallback);
+                avd.clearAnimationCallbacks();
+                avd.start();
+            }
+        });
+        Thread.sleep(500);
+        assertFalse(mAnimationStarted);
+        assertFalse(mAnimationEnded);
+    }
+
+    @Test
+    /**
+     * Test show that callback is successfully unregistered.
+     * Note that this test requires screen is on.
+     */
+    public void testUnregisterCallback() throws Throwable {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                AnimatedVectorDrawableCompat avd =
+                        setupAnimatedVectorDrawableCompat();
+
+                avd.registerAnimationCallback(mAnimationCallback);
+                avd.unregisterAnimationCallback(mAnimationCallback);
+                avd.start();
+            }
+        });
+        Thread.sleep(500);
+        assertFalse(mAnimationStarted);
+        assertFalse(mAnimationEnded);
+    }
 }
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 5f61127..3c349f9 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -17,6 +17,7 @@
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
 import android.annotation.SuppressLint;
+import android.support.annotation.RequiresApi;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -263,7 +264,7 @@
 
     @Override
     public ConstantState getConstantState() {
-        if (mDelegateDrawable != null) {
+        if (mDelegateDrawable != null && Build.VERSION.SDK_INT >= 24) {
             // Such that the configuration can be refreshed.
             return new VectorDrawableDelegateState(mDelegateDrawable.getConstantState());
         }
@@ -884,6 +885,7 @@
      * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains
      * a delegated VectorDrawable instance.
      */
+    @RequiresApi(24)
     private static class VectorDrawableDelegateState extends ConstantState {
         private final ConstantState mDelegateState;
 
diff --git a/media-compat/api26/android/support/v4/media/session/MediaControllerCompatApi26.java b/media-compat/api26/android/support/v4/media/session/MediaControllerCompatApi26.java
index bf2ca60..33829e7 100644
--- a/media-compat/api26/android/support/v4/media/session/MediaControllerCompatApi26.java
+++ b/media-compat/api26/android/support/v4/media/session/MediaControllerCompatApi26.java
@@ -16,10 +16,10 @@
 
 package android.support.v4.media.session;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.media.session.MediaController;
 
-@TargetApi(26)
+@RequiresApi(26)
 class MediaControllerCompatApi26 {
     public static Object createCallback(Callback callback) {
         return new CallbackProxy<>(callback);
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
index 5580f5a..24ec335 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
@@ -42,6 +42,7 @@
 import static android.support.v4.media.MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT_FAILED;
 import static android.support.v4.media.MediaBrowserProtocol.SERVICE_MSG_ON_LOAD_CHILDREN;
 
+import android.annotation.SuppressLint;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -59,6 +60,7 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.v4.app.BundleCompat;
 import android.support.v4.media.session.MediaControllerCompat.TransportControls;
@@ -122,11 +124,13 @@
      * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_OFFLINE
      * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_SUGGESTED
      */
+    @SuppressLint("NewApi")
     public MediaBrowserCompat(Context context, ComponentName serviceComponent,
             ConnectionCallback callback, Bundle rootHints) {
         // To workaround an issue of {@link #unsubscribe(String, SubscriptionCallback)} on API 24
         // and 25 devices, use the support library version of implementation on those devices.
-        if (Build.VERSION.SDK_INT >= 26 || BuildCompat.isAtLeastO()) {
+        if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             mImpl = new MediaBrowserImplApi24(context, serviceComponent, callback, rootHints);
         } else if (Build.VERSION.SDK_INT >= 23) {
             mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints);
@@ -600,8 +604,10 @@
         private final IBinder mToken;
         WeakReference<Subscription> mSubscriptionRef;
 
+        @SuppressLint("NewApi")
         public SubscriptionCallback() {
-            if (Build.VERSION.SDK_INT >= 26 || BuildCompat.isAtLeastO()) {
+            if (BuildCompat.isAtLeastO()) {
+                //noinspection AndroidLintNewApi
                 mSubscriptionCallbackObj =
                         MediaBrowserCompatApi24.createSubscriptionCallback(new StubApi24());
                 mToken = null;
@@ -1449,6 +1455,7 @@
         }
     }
 
+    @RequiresApi(21)
     static class MediaBrowserImplApi21 implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl,
             ConnectionCallback.ConnectionCallbackInternal {
         protected final Object mBrowserObj;
@@ -1765,6 +1772,7 @@
         }
     }
 
+    @RequiresApi(23)
     static class MediaBrowserImplApi23 extends MediaBrowserImplApi21 {
         public MediaBrowserImplApi23(Context context, ComponentName serviceComponent,
                 ConnectionCallback callback, Bundle rootHints) {
@@ -1782,6 +1790,7 @@
     }
 
     // TODO: Rename to MediaBrowserImplApi26 once O is released
+    @RequiresApi(26)
     static class MediaBrowserImplApi24 extends MediaBrowserImplApi23 {
         public MediaBrowserImplApi24(Context context, ComponentName serviceComponent,
                 ConnectionCallback callback, Bundle rootHints) {
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
index f8eb260..c94f74c 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
@@ -44,6 +44,7 @@
 import static android.support.v4.media.MediaBrowserProtocol.SERVICE_MSG_ON_LOAD_CHILDREN;
 import static android.support.v4.media.MediaBrowserProtocol.SERVICE_VERSION_CURRENT;
 
+import android.annotation.SuppressLint;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -59,6 +60,7 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.v4.app.BundleCompat;
 import android.support.v4.media.session.MediaSessionCompat;
@@ -215,13 +217,14 @@
         @Override
         public Bundle getBrowserRootHints() {
             if (mCurConnection == null) {
-                throw new IllegalStateException("This should be called inside of onLoadChildren or"
-                        + " onLoadItem methods");
+                throw new IllegalStateException("This should be called inside of onLoadChildren,"
+                        + " onLoadItem or onSearch methods");
             }
             return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
         }
     }
 
+    @RequiresApi(21)
     class MediaBrowserServiceImplApi21 implements MediaBrowserServiceImpl,
             MediaBrowserServiceCompatApi21.ServiceCompatProxy {
         Object mServiceObj;
@@ -277,8 +280,8 @@
                 return null;
             }
             if (mCurConnection == null) {
-                throw new IllegalStateException("This should be called inside of onLoadChildren or"
-                        + " onLoadItem methods");
+                throw new IllegalStateException("This should be called inside of onLoadChildren,"
+                        + " onLoadItem or onSearch methods");
             }
             return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
         }
@@ -336,6 +339,7 @@
         }
     }
 
+    @RequiresApi(23)
     class MediaBrowserServiceImplApi23 extends MediaBrowserServiceImplApi21 implements
             MediaBrowserServiceCompatApi23.ServiceCompatProxy {
         @Override
@@ -371,6 +375,7 @@
     }
 
     // TODO: Rename to MediaBrowserServiceImplApi26 once O is released
+    @RequiresApi(26)
     class MediaBrowserServiceImplApi24 extends MediaBrowserServiceImplApi23 implements
             MediaBrowserServiceCompatApi26.ServiceCompatProxy {
         @Override
@@ -550,6 +555,7 @@
      *
      * @see MediaBrowserServiceCompat#onLoadChildren
      * @see MediaBrowserServiceCompat#onLoadItem
+     * @see MediaBrowserServiceCompat#onSearch
      */
     public static class Result<T> {
         private Object mDebug;
@@ -850,9 +856,11 @@
     }
 
     @Override
+    @SuppressLint("NewApi")
     public void onCreate() {
         super.onCreate();
-        if (Build.VERSION.SDK_INT >= 26 || BuildCompat.isAtLeastO()) {
+        if (BuildCompat.isAtLeastO()) {
+            //noinspection AndroidLintNewApi
             mImpl = new MediaBrowserServiceImplApi24();
         } else if (Build.VERSION.SDK_INT >= 23) {
             mImpl = new MediaBrowserServiceImplApi23();
@@ -1039,8 +1047,8 @@
      * Note that this will return null when connected to {@link android.media.browse.MediaBrowser}
      * and running on API 23 or lower.
      *
-     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren}
-     *             or {@link #onLoadItem}
+     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren},
+     *             {@link #onLoadItem} or {@link #onSearch}.
      * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_RECENT
      * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_OFFLINE
      * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_SUGGESTED
diff --git a/media-compat/java/android/support/v4/media/MediaDescriptionCompat.java b/media-compat/java/android/support/v4/media/MediaDescriptionCompat.java
index 1a617e9..37643d8 100644
--- a/media-compat/java/android/support/v4/media/MediaDescriptionCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaDescriptionCompat.java
@@ -334,44 +334,44 @@
      *         none.
      */
     public static MediaDescriptionCompat fromMediaDescription(Object descriptionObj) {
-        if (descriptionObj == null || Build.VERSION.SDK_INT < 21) {
+        if (descriptionObj != null && Build.VERSION.SDK_INT >= 21) {
+            Builder bob = new Builder();
+            bob.setMediaId(MediaDescriptionCompatApi21.getMediaId(descriptionObj));
+            bob.setTitle(MediaDescriptionCompatApi21.getTitle(descriptionObj));
+            bob.setSubtitle(MediaDescriptionCompatApi21.getSubtitle(descriptionObj));
+            bob.setDescription(MediaDescriptionCompatApi21.getDescription(descriptionObj));
+            bob.setIconBitmap(MediaDescriptionCompatApi21.getIconBitmap(descriptionObj));
+            bob.setIconUri(MediaDescriptionCompatApi21.getIconUri(descriptionObj));
+            Bundle extras = MediaDescriptionCompatApi21.getExtras(descriptionObj);
+            Uri mediaUri = extras == null ? null :
+                    (Uri) extras.getParcelable(DESCRIPTION_KEY_MEDIA_URI);
+            if (mediaUri != null) {
+                if (extras.containsKey(DESCRIPTION_KEY_NULL_BUNDLE_FLAG) && extras.size() == 2) {
+                    // The extras were only created for the media URI, so we set it back to null to
+                    // ensure mediaDescriptionCompat.getExtras() equals
+                    // fromMediaDescription(getMediaDescription(mediaDescriptionCompat)).getExtras()
+                    extras = null;
+                } else {
+                    // Remove media URI keys to ensure mediaDescriptionCompat.getExtras().keySet()
+                    // equals fromMediaDescription(getMediaDescription(mediaDescriptionCompat))
+                    // .getExtras().keySet()
+                    extras.remove(DESCRIPTION_KEY_MEDIA_URI);
+                    extras.remove(DESCRIPTION_KEY_NULL_BUNDLE_FLAG);
+                }
+            }
+            bob.setExtras(extras);
+            if (mediaUri != null) {
+                bob.setMediaUri(mediaUri);
+            } else if (Build.VERSION.SDK_INT >= 23) {
+                bob.setMediaUri(MediaDescriptionCompatApi23.getMediaUri(descriptionObj));
+            }
+            MediaDescriptionCompat descriptionCompat = bob.build();
+            descriptionCompat.mDescriptionObj = descriptionObj;
+
+            return descriptionCompat;
+        } else {
             return null;
         }
-
-        Builder bob = new Builder();
-        bob.setMediaId(MediaDescriptionCompatApi21.getMediaId(descriptionObj));
-        bob.setTitle(MediaDescriptionCompatApi21.getTitle(descriptionObj));
-        bob.setSubtitle(MediaDescriptionCompatApi21.getSubtitle(descriptionObj));
-        bob.setDescription(MediaDescriptionCompatApi21.getDescription(descriptionObj));
-        bob.setIconBitmap(MediaDescriptionCompatApi21.getIconBitmap(descriptionObj));
-        bob.setIconUri(MediaDescriptionCompatApi21.getIconUri(descriptionObj));
-        Bundle extras = MediaDescriptionCompatApi21.getExtras(descriptionObj);
-        Uri mediaUri = extras == null ? null :
-                (Uri) extras.getParcelable(DESCRIPTION_KEY_MEDIA_URI);
-        if (mediaUri != null) {
-            if (extras.containsKey(DESCRIPTION_KEY_NULL_BUNDLE_FLAG) && extras.size() == 2) {
-                // The extras were only created for the media URI, so we set it back to null to
-                // ensure mediaDescriptionCompat.getExtras() equals
-                // fromMediaDescription(getMediaDescription(mediaDescriptionCompat)).getExtras()
-                extras = null;
-            } else {
-                // Remove media URI keys to ensure mediaDescriptionCompat.getExtras().keySet()
-                // equals fromMediaDescription(getMediaDescription(mediaDescriptionCompat))
-                // .getExtras().keySet()
-                extras.remove(DESCRIPTION_KEY_MEDIA_URI);
-                extras.remove(DESCRIPTION_KEY_NULL_BUNDLE_FLAG);
-            }
-        }
-        bob.setExtras(extras);
-        if (mediaUri != null) {
-            bob.setMediaUri(mediaUri);
-        } else if (Build.VERSION.SDK_INT >= 23) {
-            bob.setMediaUri(MediaDescriptionCompatApi23.getMediaUri(descriptionObj));
-        }
-        MediaDescriptionCompat descriptionCompat = bob.build();
-        descriptionCompat.mDescriptionObj = descriptionObj;
-
-        return descriptionCompat;
     }
 
     public static final Parcelable.Creator<MediaDescriptionCompat> CREATOR =
diff --git a/media-compat/java/android/support/v4/media/MediaMetadataCompat.java b/media-compat/java/android/support/v4/media/MediaMetadataCompat.java
index f8c1f57..58c1147 100644
--- a/media-compat/java/android/support/v4/media/MediaMetadataCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaMetadataCompat.java
@@ -580,17 +580,17 @@
      *         none.
      */
     public static MediaMetadataCompat fromMediaMetadata(Object metadataObj) {
-        if (metadataObj == null || Build.VERSION.SDK_INT < 21) {
+        if (metadataObj != null && Build.VERSION.SDK_INT >= 21) {
+            Parcel p = Parcel.obtain();
+            MediaMetadataCompatApi21.writeToParcel(metadataObj, p, 0);
+            p.setDataPosition(0);
+            MediaMetadataCompat metadata = MediaMetadataCompat.CREATOR.createFromParcel(p);
+            p.recycle();
+            metadata.mMetadataObj = metadataObj;
+            return metadata;
+        } else {
             return null;
         }
-
-        Parcel p = Parcel.obtain();
-        MediaMetadataCompatApi21.writeToParcel(metadataObj, p, 0);
-        p.setDataPosition(0);
-        MediaMetadataCompat metadata = MediaMetadataCompat.CREATOR.createFromParcel(p);
-        p.recycle();
-        metadata.mMetadataObj = metadataObj;
-        return metadata;
     }
 
     /**
@@ -604,15 +604,13 @@
      *         if none.
      */
     public Object getMediaMetadata() {
-        if (mMetadataObj != null || Build.VERSION.SDK_INT < 21) {
-            return mMetadataObj;
+        if (mMetadataObj == null && Build.VERSION.SDK_INT >= 21) {
+            Parcel p = Parcel.obtain();
+            writeToParcel(p, 0);
+            p.setDataPosition(0);
+            mMetadataObj = MediaMetadataCompatApi21.createFromParcel(p);
+            p.recycle();
         }
-
-        Parcel p = Parcel.obtain();
-        writeToParcel(p, 0);
-        p.setDataPosition(0);
-        mMetadataObj = MediaMetadataCompatApi21.createFromParcel(p);
-        p.recycle();
         return mMetadataObj;
     }
 
@@ -662,7 +660,7 @@
          * <p>
          * This also deep-copies the bitmaps for {@link #METADATA_KEY_ART} and
          * {@link #METADATA_KEY_ALBUM_ART} on
-         * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWITCH} and later
+         * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and later
          * to prevent bitmaps from being recycled by RCC.
          *
          * @param source The original metadata to copy.
diff --git a/media-compat/java/android/support/v4/media/RatingCompat.java b/media-compat/java/android/support/v4/media/RatingCompat.java
index f61a686..e8cb10d 100644
--- a/media-compat/java/android/support/v4/media/RatingCompat.java
+++ b/media-compat/java/android/support/v4/media/RatingCompat.java
@@ -324,37 +324,38 @@
      * @return An equivalent {@link RatingCompat} object, or null if none.
      */
     public static RatingCompat fromRating(Object ratingObj) {
-        if (ratingObj == null || Build.VERSION.SDK_INT < 19) {
+        if (ratingObj != null && Build.VERSION.SDK_INT >= 19) {
+            final int ratingStyle = RatingCompatKitkat.getRatingStyle(ratingObj);
+            final RatingCompat rating;
+            if (RatingCompatKitkat.isRated(ratingObj)) {
+                switch (ratingStyle) {
+                    case RATING_HEART:
+                        rating = newHeartRating(RatingCompatKitkat.hasHeart(ratingObj));
+                        break;
+                    case RATING_THUMB_UP_DOWN:
+                        rating = newThumbRating(RatingCompatKitkat.isThumbUp(ratingObj));
+                        break;
+                    case RATING_3_STARS:
+                    case RATING_4_STARS:
+                    case RATING_5_STARS:
+                        rating = newStarRating(ratingStyle,
+                                RatingCompatKitkat.getStarRating(ratingObj));
+                        break;
+                    case RATING_PERCENTAGE:
+                        rating = newPercentageRating(
+                                RatingCompatKitkat.getPercentRating(ratingObj));
+                        break;
+                    default:
+                        return null;
+                }
+            } else {
+                rating = newUnratedRating(ratingStyle);
+            }
+            rating.mRatingObj = ratingObj;
+            return rating;
+        } else {
             return null;
         }
-
-        final int ratingStyle = RatingCompatKitkat.getRatingStyle(ratingObj);
-        final RatingCompat rating;
-        if (RatingCompatKitkat.isRated(ratingObj)) {
-            switch (ratingStyle) {
-                case RATING_HEART:
-                    rating = newHeartRating(RatingCompatKitkat.hasHeart(ratingObj));
-                    break;
-                case RATING_THUMB_UP_DOWN:
-                    rating = newThumbRating(RatingCompatKitkat.isThumbUp(ratingObj));
-                    break;
-                case RATING_3_STARS:
-                case RATING_4_STARS:
-                case RATING_5_STARS:
-                    rating = newStarRating(ratingStyle,
-                            RatingCompatKitkat.getStarRating(ratingObj));
-                    break;
-                case RATING_PERCENTAGE:
-                    rating = newPercentageRating(RatingCompatKitkat.getPercentRating(ratingObj));
-                    break;
-                default:
-                    return null;
-            }
-        } else {
-            rating = newUnratedRating(ratingStyle);
-        }
-        rating.mRatingObj = ratingObj;
-        return rating;
     }
 
     /**
@@ -366,30 +367,29 @@
      * @return An equivalent {@link android.media.Rating} object, or null if none.
      */
     public Object getRating() {
-        if (mRatingObj != null || Build.VERSION.SDK_INT < 19) {
-            return mRatingObj;
-        }
-
-        if (isRated()) {
-            switch (mRatingStyle) {
-                case RATING_HEART:
-                    mRatingObj = RatingCompatKitkat.newHeartRating(hasHeart());
-                    break;
-                case RATING_THUMB_UP_DOWN:
-                    mRatingObj = RatingCompatKitkat.newThumbRating(isThumbUp());
-                    break;
-                case RATING_3_STARS:
-                case RATING_4_STARS:
-                case RATING_5_STARS:
-                    mRatingObj = RatingCompatKitkat.newStarRating(mRatingStyle, getStarRating());
-                    break;
-                case RATING_PERCENTAGE:
-                    mRatingObj = RatingCompatKitkat.newPercentageRating(getPercentRating());
-                default:
-                    return null;
+        if (mRatingObj == null && Build.VERSION.SDK_INT >= 19) {
+            if (isRated()) {
+                switch (mRatingStyle) {
+                    case RATING_HEART:
+                        mRatingObj = RatingCompatKitkat.newHeartRating(hasHeart());
+                        break;
+                    case RATING_THUMB_UP_DOWN:
+                        mRatingObj = RatingCompatKitkat.newThumbRating(isThumbUp());
+                        break;
+                    case RATING_3_STARS:
+                    case RATING_4_STARS:
+                    case RATING_5_STARS:
+                        mRatingObj = RatingCompatKitkat.newStarRating(mRatingStyle,
+                                getStarRating());
+                        break;
+                    case RATING_PERCENTAGE:
+                        mRatingObj = RatingCompatKitkat.newPercentageRating(getPercentRating());
+                    default:
+                        return null;
+                }
+            } else {
+                mRatingObj = RatingCompatKitkat.newUnratedRating(mRatingStyle);
             }
-        } else {
-            mRatingObj = RatingCompatKitkat.newUnratedRating(mRatingStyle);
         }
         return mRatingObj;
     }
diff --git a/media-compat/java/android/support/v4/media/TransportMediator.java b/media-compat/java/android/support/v4/media/TransportMediator.java
index 40c245c..cb10bb1 100644
--- a/media-compat/java/android/support/v4/media/TransportMediator.java
+++ b/media-compat/java/android/support/v4/media/TransportMediator.java
@@ -259,7 +259,10 @@
      */
     @Deprecated
     public Object getRemoteControlClient() {
-        return mController != null ? mController.getRemoteControlClient() : null;
+        if (Build.VERSION.SDK_INT >= 18) {
+            return mController != null ? mController.getRemoteControlClient() : null;
+        }
+        return null;
     }
 
     /**
@@ -327,7 +330,7 @@
     }
 
     private void pushControllerState() {
-        if (mController != null) {
+        if (mController != null && Build.VERSION.SDK_INT >= 18) {
             mController.refreshState(mCallbacks.onIsPlaying(),
                     mCallbacks.onGetCurrentPosition(),
                     mCallbacks.onGetTransportControlFlags());
@@ -353,7 +356,7 @@
     @Deprecated
     @Override
     public void startPlaying() {
-        if (mController != null) {
+        if (mController != null && Build.VERSION.SDK_INT >= 18) {
             mController.startPlaying();
         }
         mCallbacks.onStart();
@@ -370,7 +373,7 @@
     @Deprecated
     @Override
     public void pausePlaying() {
-        if (mController != null) {
+        if (mController != null && Build.VERSION.SDK_INT >= 18) {
             mController.pausePlaying();
         }
         mCallbacks.onPause();
@@ -387,7 +390,7 @@
     @Deprecated
     @Override
     public void stopPlaying() {
-        if (mController != null) {
+        if (mController != null && Build.VERSION.SDK_INT >= 18) {
             mController.stopPlaying();
         }
         mCallbacks.onStop();
@@ -483,6 +486,8 @@
      */
     @Deprecated
     public void destroy() {
-        mController.destroy();
+        if (mController != null && Build.VERSION.SDK_INT >= 18) {
+            mController.destroy();
+        }
     }
 }
diff --git a/media-compat/java/android/support/v4/media/VolumeProviderCompat.java b/media-compat/java/android/support/v4/media/VolumeProviderCompat.java
index a3aa047..3085969 100644
--- a/media-compat/java/android/support/v4/media/VolumeProviderCompat.java
+++ b/media-compat/java/android/support/v4/media/VolumeProviderCompat.java
@@ -121,7 +121,7 @@
     public final void setCurrentVolume(int currentVolume) {
         mCurrentVolume = currentVolume;
         Object volumeProviderObj = getVolumeProvider();
-        if (volumeProviderObj != null) {
+        if (volumeProviderObj != null && Build.VERSION.SDK_INT >= 21) {
             VolumeProviderCompatApi21.setCurrentVolume(volumeProviderObj, currentVolume);
         }
         if (mCallback != null) {
@@ -164,23 +164,22 @@
      * @return An equivalent {@link android.media.VolumeProvider} object, or null if none.
      */
     public Object getVolumeProvider() {
-        if (mVolumeProviderObj != null || Build.VERSION.SDK_INT < 21) {
-            return mVolumeProviderObj;
+        if (mVolumeProviderObj == null && Build.VERSION.SDK_INT >= 21) {
+            mVolumeProviderObj = VolumeProviderCompatApi21.createVolumeProvider(
+                    mControlType, mMaxVolume, mCurrentVolume,
+                    new VolumeProviderCompatApi21.Delegate() {
+
+                        @Override
+                        public void onSetVolumeTo(int volume) {
+                            VolumeProviderCompat.this.onSetVolumeTo(volume);
+                        }
+
+                        @Override
+                        public void onAdjustVolume(int direction) {
+                            VolumeProviderCompat.this.onAdjustVolume(direction);
+                        }
+                    });
         }
-
-        mVolumeProviderObj = VolumeProviderCompatApi21.createVolumeProvider(
-                mControlType, mMaxVolume, mCurrentVolume, new VolumeProviderCompatApi21.Delegate() {
-
-            @Override
-            public void onSetVolumeTo(int volume) {
-                VolumeProviderCompat.this.onSetVolumeTo(volume);
-            }
-
-            @Override
-            public void onAdjustVolume(int direction) {
-                VolumeProviderCompat.this.onAdjustVolume(direction);
-            }
-        });
         return mVolumeProviderObj;
     }
 
diff --git a/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java b/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
index 4f9fe6d..3e28274 100644
--- a/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
+++ b/media-compat/java/android/support/v4/media/session/MediaControllerCompat.java
@@ -28,6 +28,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.app.BundleCompat;
 import android.support.v4.app.SupportActivity;
@@ -1621,6 +1622,7 @@
         }
     }
 
+    @RequiresApi(21)
     static class MediaControllerImplApi21 implements MediaControllerImpl {
         protected final Object mControllerObj;
 
@@ -2114,6 +2116,7 @@
         }
     }
 
+    @RequiresApi(23)
     static class MediaControllerImplApi23 extends MediaControllerImplApi21 {
 
         public MediaControllerImplApi23(Context context, MediaSessionCompat session) {
@@ -2132,6 +2135,7 @@
         }
     }
 
+    @RequiresApi(23)
     static class TransportControlsApi23 extends TransportControlsApi21 {
 
         public TransportControlsApi23(Object controlsObj) {
@@ -2145,6 +2149,7 @@
         }
     }
 
+    @RequiresApi(24)
     static class MediaControllerImplApi24 extends MediaControllerImplApi23 {
 
         public MediaControllerImplApi24(Context context, MediaSessionCompat session) {
@@ -2163,6 +2168,7 @@
         }
     }
 
+    @RequiresApi(24)
     static class TransportControlsApi24 extends TransportControlsApi23 {
 
         public TransportControlsApi24(Object controlsObj) {
@@ -2192,6 +2198,7 @@
         }
     }
 
+    @RequiresApi(26)
     static class MediaControllerImplApi26 extends MediaControllerImplApi24 {
 
         MediaControllerImplApi26(Context context, MediaSessionCompat session) {
@@ -2220,6 +2227,7 @@
         }
     }
 
+    @RequiresApi(26)
     static class TransportControlsApi26 extends TransportControlsApi24 {
 
         TransportControlsApi26(Object controlsObj) {
diff --git a/media-compat/java/android/support/v4/media/session/MediaSessionCompat.java b/media-compat/java/android/support/v4/media/session/MediaSessionCompat.java
index a186c95..710de2b 100644
--- a/media-compat/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/media-compat/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -681,10 +681,10 @@
      * @return An equivalent {@link MediaSessionCompat} object, or null if none.
      */
     public static MediaSessionCompat fromMediaSession(Context context, Object mediaSession) {
-        if (context == null || mediaSession == null || Build.VERSION.SDK_INT < 21) {
-            return null;
+        if (context != null && mediaSession != null && Build.VERSION.SDK_INT >= 21) {
+            return new MediaSessionCompat(context, new MediaSessionImplApi21(mediaSession));
         }
-        return new MediaSessionCompat(context, new MediaSessionImplApi21(mediaSession));
+        return null;
     }
 
     /**
@@ -944,6 +944,7 @@
         public void onRemoveQueueItemAt(int index) {
         }
 
+        @RequiresApi(21)
         private class StubApi21 implements MediaSessionCompatApi21.Callback {
 
             StubApi21() {
@@ -1079,6 +1080,7 @@
             }
         }
 
+        @RequiresApi(23)
         private class StubApi23 extends StubApi21 implements MediaSessionCompatApi23.Callback {
 
             StubApi23() {
@@ -1090,6 +1092,7 @@
             }
         }
 
+        @RequiresApi(24)
         private class StubApi24 extends StubApi23 implements MediaSessionCompatApi24.Callback {
 
             StubApi24() {
@@ -1116,6 +1119,7 @@
             }
         }
 
+        @RequiresApi(26)
         private class StubApi26 extends StubApi24 implements MediaSessionCompatApi26.Callback {
             @Override
             public void onSetRepeatMode(int repeatMode) {
@@ -1153,10 +1157,10 @@
          * @return A compat Token for use with {@link MediaControllerCompat}.
          */
         public static Token fromToken(Object token) {
-            if (token == null || android.os.Build.VERSION.SDK_INT < 21) {
-                return null;
+            if (token != null && android.os.Build.VERSION.SDK_INT >= 21) {
+                return new Token(MediaSessionCompatApi21.verifyToken(token));
             }
-            return new Token(MediaSessionCompatApi21.verifyToken(token));
+            return null;
         }
 
         @Override
diff --git a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
index 815fe95..ab85133 100644
--- a/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
+++ b/media-compat/java/android/support/v4/media/session/PlaybackStateCompat.java
@@ -713,35 +713,38 @@
      * @return An equivalent {@link PlaybackStateCompat} object, or null if none.
      */
     public static PlaybackStateCompat fromPlaybackState(Object stateObj) {
-        if (stateObj == null || Build.VERSION.SDK_INT < 21) {
+        if (stateObj != null && Build.VERSION.SDK_INT >= 21) {
+            List<Object> customActionObjs = PlaybackStateCompatApi21.getCustomActions(stateObj);
+            List<PlaybackStateCompat.CustomAction> customActions = null;
+            if (customActionObjs != null) {
+                customActions = new ArrayList<>(customActionObjs.size());
+                for (Object customActionObj : customActionObjs) {
+                    customActions.add(CustomAction.fromCustomAction(customActionObj));
+                }
+            }
+            Bundle extras;
+            if (Build.VERSION.SDK_INT >= 22) {
+                extras = PlaybackStateCompatApi22.getExtras(stateObj);
+            } else {
+                extras = null;
+            }
+            PlaybackStateCompat state = new PlaybackStateCompat(
+                    PlaybackStateCompatApi21.getState(stateObj),
+                    PlaybackStateCompatApi21.getPosition(stateObj),
+                    PlaybackStateCompatApi21.getBufferedPosition(stateObj),
+                    PlaybackStateCompatApi21.getPlaybackSpeed(stateObj),
+                    PlaybackStateCompatApi21.getActions(stateObj),
+                    ERROR_CODE_UNKNOWN_ERROR,
+                    PlaybackStateCompatApi21.getErrorMessage(stateObj),
+                    PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj),
+                    customActions,
+                    PlaybackStateCompatApi21.getActiveQueueItemId(stateObj),
+                    extras);
+            state.mStateObj = stateObj;
+            return state;
+        } else {
             return null;
         }
-
-        List<Object> customActionObjs = PlaybackStateCompatApi21.getCustomActions(stateObj);
-        List<PlaybackStateCompat.CustomAction> customActions = null;
-        if (customActionObjs != null) {
-            customActions = new ArrayList<>(customActionObjs.size());
-            for (Object customActionObj : customActionObjs) {
-                customActions.add(CustomAction.fromCustomAction(customActionObj));
-            }
-        }
-        Bundle extras = Build.VERSION.SDK_INT >= 22
-                ? PlaybackStateCompatApi22.getExtras(stateObj)
-                : null;
-        PlaybackStateCompat state = new PlaybackStateCompat(
-                PlaybackStateCompatApi21.getState(stateObj),
-                PlaybackStateCompatApi21.getPosition(stateObj),
-                PlaybackStateCompatApi21.getBufferedPosition(stateObj),
-                PlaybackStateCompatApi21.getPlaybackSpeed(stateObj),
-                PlaybackStateCompatApi21.getActions(stateObj),
-                ERROR_CODE_UNKNOWN_ERROR,
-                PlaybackStateCompatApi21.getErrorMessage(stateObj),
-                PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj),
-                customActions,
-                PlaybackStateCompatApi21.getActiveQueueItemId(stateObj),
-                extras);
-        state.mStateObj = stateObj;
-        return state;
     }
 
     /**
@@ -753,25 +756,26 @@
      * @return An equivalent {@link android.media.session.PlaybackState} object, or null if none.
      */
     public Object getPlaybackState() {
-        if (mStateObj != null || Build.VERSION.SDK_INT < 21) {
-            return mStateObj;
-        }
-
-        List<Object> customActions = null;
-        if (mCustomActions != null) {
-            customActions = new ArrayList<>(mCustomActions.size());
-            for (PlaybackStateCompat.CustomAction customAction : mCustomActions) {
-                customActions.add(customAction.getCustomAction());
+        if (mStateObj == null && Build.VERSION.SDK_INT >= 21) {
+            List<Object> customActions = null;
+            if (mCustomActions != null) {
+                customActions = new ArrayList<>(mCustomActions.size());
+                for (PlaybackStateCompat.CustomAction customAction : mCustomActions) {
+                    customActions.add(customAction.getCustomAction());
+                }
             }
-        }
-        if (Build.VERSION.SDK_INT >= 22) {
-            mStateObj = PlaybackStateCompatApi22.newInstance(mState, mPosition, mBufferedPosition,
-                    mSpeed, mActions, mErrorMessage, mUpdateTime,
-                    customActions, mActiveItemId, mExtras);
-        } else {
-            mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition, mBufferedPosition,
-                    mSpeed, mActions, mErrorMessage, mUpdateTime,
-                    customActions, mActiveItemId);
+            if (Build.VERSION.SDK_INT >= 22) {
+                mStateObj = PlaybackStateCompatApi22.newInstance(mState, mPosition,
+                        mBufferedPosition,
+                        mSpeed, mActions, mErrorMessage, mUpdateTime,
+                        customActions, mActiveItemId, mExtras);
+            } else if (Build.VERSION.SDK_INT >= 21) {
+                // The extra conditional is necessary to pass the NewApi Lint inspection.
+                mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition,
+                        mBufferedPosition,
+                        mSpeed, mActions, mErrorMessage, mUpdateTime,
+                        customActions, mActiveItemId);
+            }
         }
         return mStateObj;
     }
diff --git a/media-compat/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java b/media-compat/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
index c27a716..a3b4eed 100644
--- a/media-compat/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
+++ b/media-compat/jellybean-mr2/android/support/v4/media/TransportMediatorJellybeanMR2.java
@@ -84,11 +84,12 @@
             };
     final RemoteControlClient.OnPlaybackPositionUpdateListener mPlaybackPositionUpdateListener
             = new RemoteControlClient.OnPlaybackPositionUpdateListener() {
+                @Override
                 public void onPlaybackPositionUpdate(long newPositionMs) {
                     mTransportCallback.playbackPositionUpdate(newPositionMs);
                 }
             };
- 
+
     PendingIntent mPendingIntent;
     RemoteControlClient mRemoteControl;
     boolean mFocused;
diff --git a/pathmap.mk b/pathmap.mk
new file mode 100644
index 0000000..fd29ee1
--- /dev/null
+++ b/pathmap.mk
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2016 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.
+#
+
+#
+# A list of all source roots under frameworks/support.
+#
+FRAMEWORKS_SUPPORT_SUBDIRS := \
+    annotations \
+    compat \
+    media-compat \
+    fragment \
+    core-ui \
+    core-utils \
+    v7/gridlayout \
+    v7/cardview \
+    v7/mediarouter \
+    v7/palette \
+    v13 \
+    v17/leanback \
+    design \
+    percent \
+    recommendation \
+    transition \
+    v7/preference \
+    v14/preference \
+    v17/preference-leanback \
+    customtabs \
+    exifinterface \
+    dynamic-animation
+
+#
+# A version of FRAMEWORKS_SUPPORT_SUBDIRS that is expanded to full paths from
+# the root of the tree.
+#
+FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS := \
+    $(addprefix frameworks/support/,$(FRAMEWORKS_SUPPORT_SUBDIRS)) \
+    frameworks/support/graphics/drawable/animated \
+    frameworks/support/graphics/drawable/static \
+    frameworks/support/v7/appcompat/src \
+    frameworks/support/v7/recyclerview/src
+
+#
+# A list of support library modules.
+#
+FRAMEWORKS_SUPPORT_JAVA_LIBRARIES := \
+    $(foreach dir,$(FRAMEWORKS_SUPPORT_SUBDIRS),android-support-$(subst /,-,$(dir))) \
+    android-support-v4 \
+    android-support-vectordrawable \
+    android-support-animatedvectordrawable \
+    android-support-v7-appcompat \
+    android-support-v7-recyclerview
diff --git a/samples/Support13Demos/build.gradle b/samples/Support13Demos/build.gradle
index 0436bf7..096a8bc 100644
--- a/samples/Support13Demos/build.gradle
+++ b/samples/Support13Demos/build.gradle
@@ -19,6 +19,7 @@
     }
 
     lintOptions {
+        checkReleaseBuilds false
         abortOnError false
     }
 
diff --git a/samples/Support13Demos/src/com/example/android/supportv13/Support13Demos.java b/samples/Support13Demos/src/com/example/android/supportv13/Support13Demos.java
index fda4b34..7db027d 100644
--- a/samples/Support13Demos/src/com/example/android/supportv13/Support13Demos.java
+++ b/samples/Support13Demos/src/com/example/android/supportv13/Support13Demos.java
@@ -113,6 +113,7 @@
         new Comparator<Map<String, Object>>() {
         private final Collator   collator = Collator.getInstance();
 
+        @Override
         public int compare(Map<String, Object> map1, Map<String, Object> map2) {
             return collator.compare(map1.get("title"), map2.get("title"));
         }
diff --git a/samples/Support13Demos/src/com/example/android/supportv13/app/CursorFragment.java b/samples/Support13Demos/src/com/example/android/supportv13/app/CursorFragment.java
index 57f0e10..ee311fc 100644
--- a/samples/Support13Demos/src/com/example/android/supportv13/app/CursorFragment.java
+++ b/samples/Support13Demos/src/com/example/android/supportv13/app/CursorFragment.java
@@ -81,6 +81,7 @@
         item.setActionView(sv);
     }
 
+    @Override
     public boolean onQueryTextChange(String newText) {
         // Called when the action bar search text has changed.  Update
         // the search filter, and restart the loader to do a new query
@@ -110,6 +111,7 @@
         Contacts.LOOKUP_KEY,
     };
 
+    @Override
     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
         // This is called when a new Loader needs to be created.  This
         // sample only has one Loader, so we don't care about the ID.
@@ -133,6 +135,7 @@
                 Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
     }
 
+    @Override
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
         // Swap the new cursor in.  (The framework will take care of closing the
         // old cursor once we return.)
@@ -146,6 +149,7 @@
         }
     }
 
+    @Override
     public void onLoaderReset(Loader<Cursor> loader) {
         // This is called when the last Cursor provided to onLoadFinished()
         // above is about to be closed.  We need to make sure we are no
diff --git a/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentPagerSupport.java b/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentPagerSupport.java
index 04532b8..3d169c8 100644
--- a/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentPagerSupport.java
+++ b/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentPagerSupport.java
@@ -58,12 +58,14 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.goto_first);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(0);
             }
         });
         button = (Button)findViewById(R.id.goto_last);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(NUM_ITEMS-1);
             }
diff --git a/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java b/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java
index e60c268..cec71dd 100644
--- a/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java
+++ b/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java
@@ -58,12 +58,14 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.goto_first);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(0);
             }
         });
         button = (Button)findViewById(R.id.goto_last);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(NUM_ITEMS-1);
             }
diff --git a/samples/Support13Demos/src/com/example/android/supportv13/view/CheckableFrameLayout.java b/samples/Support13Demos/src/com/example/android/supportv13/view/CheckableFrameLayout.java
index f642e8e..e2383de 100644
--- a/samples/Support13Demos/src/com/example/android/supportv13/view/CheckableFrameLayout.java
+++ b/samples/Support13Demos/src/com/example/android/supportv13/view/CheckableFrameLayout.java
@@ -33,15 +33,18 @@
         super(context, attrs);
     }
 
+    @Override
     public void setChecked(boolean checked) {
         mChecked = checked;
         setBackgroundDrawable(checked ? new ColorDrawable(0xff0000a0) : null);
     }
 
+    @Override
     public boolean isChecked() {
         return mChecked;
     }
 
+    @Override
     public void toggle() {
         setChecked(!mChecked);
     }
diff --git a/samples/Support4Demos/build.gradle b/samples/Support4Demos/build.gradle
index ea1808a..4cf38d9 100644
--- a/samples/Support4Demos/build.gradle
+++ b/samples/Support4Demos/build.gradle
@@ -19,6 +19,7 @@
     }
 
     lintOptions {
+        checkReleaseBuilds false
         abortOnError true
     }
 
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/Support4Demos.java b/samples/Support4Demos/src/com/example/android/supportv4/Support4Demos.java
index af445db..a90551f 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/Support4Demos.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/Support4Demos.java
@@ -38,10 +38,10 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
         Intent intent = getIntent();
         String path = intent.getStringExtra("com.example.android.apis.Path");
-        
+
         if (path == null) {
             path = "";
         }
@@ -66,16 +66,16 @@
 
         String[] prefixPath;
         String prefixWithSlash = prefix;
-        
+
         if (prefix.equals("")) {
             prefixPath = null;
         } else {
             prefixPath = prefix.split("/");
             prefixWithSlash = prefix + "/";
         }
-        
+
         int len = list.size();
-        
+
         Map<String, Boolean> entries = new HashMap<String, Boolean>();
 
         for (int i = 0; i < len; i++) {
@@ -84,9 +84,9 @@
             String label = labelSeq != null
                     ? labelSeq.toString()
                     : info.activityInfo.name;
-            
+
             if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
-                
+
                 String[] labelPath = label.split("/");
 
                 String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
@@ -105,7 +105,7 @@
         }
 
         Collections.sort(myData, sDisplayNameComparator);
-        
+
         return myData;
     }
 
@@ -113,6 +113,7 @@
         new Comparator<Map<String, Object>>() {
         private final Collator   collator = Collator.getInstance();
 
+        @Override
         public int compare(Map<String, Object> map1, Map<String, Object> map2) {
             return collator.compare(map1.get("title"), map2.get("title"));
         }
@@ -123,7 +124,7 @@
         result.setClassName(pkg, componentName);
         return result;
     }
-    
+
     protected Intent browseIntent(String path) {
         Intent result = new Intent();
         result.setClass(this, Support4Demos.class);
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentAlertDialogSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentAlertDialogSupport.java
index f35e021..c651fdc 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentAlertDialogSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentAlertDialogSupport.java
@@ -47,6 +47,7 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.show);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 showDialog();
             }
@@ -91,6 +92,7 @@
                     .setTitle(title)
                     .setPositiveButton(R.string.alert_dialog_ok,
                         new DialogInterface.OnClickListener() {
+                            @Override
                             public void onClick(DialogInterface dialog, int whichButton) {
                                 ((FragmentAlertDialogSupport)getActivity()).doPositiveClick();
                             }
@@ -98,6 +100,7 @@
                     )
                     .setNegativeButton(R.string.alert_dialog_cancel,
                         new DialogInterface.OnClickListener() {
+                            @Override
                             public void onClick(DialogInterface dialog, int whichButton) {
                                 ((FragmentAlertDialogSupport)getActivity()).doNegativeClick();
                             }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentCustomAnimationSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentCustomAnimationSupport.java
index 478cb7d..917b614 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentCustomAnimationSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentCustomAnimationSupport.java
@@ -42,6 +42,7 @@
         // Watch for button clicks.
         Button button = (Button) findViewById(R.id.new_fragment);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 addFragmentToStack();
             }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogOrActivitySupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogOrActivitySupport.java
index 06b2730..dd5cca7 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogOrActivitySupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogOrActivitySupport.java
@@ -48,6 +48,7 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.show_dialog);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 showDialog();
             }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogSupport.java
index b387bfc..140e920 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentDialogSupport.java
@@ -48,6 +48,7 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.show);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 showDialog();
             }
@@ -155,6 +156,7 @@
             // Watch for button clicks.
             Button button = (Button)v.findViewById(R.id.show);
             button.setOnClickListener(new OnClickListener() {
+                @Override
                 public void onClick(View v) {
                     // When button is clicked, call up to owning activity.
                     ((FragmentDialogSupport)getActivity()).showDialog();
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentHideShowSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentHideShowSupport.java
index 3441506..0e8fe46 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentHideShowSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentHideShowSupport.java
@@ -57,6 +57,7 @@
     void addShowHideListener(int buttonId, final Fragment fragment) {
         final Button button = (Button)findViewById(buttonId);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                 ft.setCustomAnimations(android.R.anim.fade_in,
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuFragmentSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuFragmentSupport.java
index fb65a2b..b8d60d6 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuFragmentSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuFragmentSupport.java
@@ -40,6 +40,7 @@
 
     // Update fragment visibility when check boxes are changed.
     final OnClickListener mClickListener = new OnClickListener() {
+        @Override
         public void onClick(View v) {
             updateFragmentVisibility();
         }
@@ -64,13 +65,13 @@
             ft.add(mFragment2, "f2");
         }
         ft.commit();
-        
+
         // Watch check box clicks.
         mCheckBox1 = (CheckBox)v.findViewById(R.id.menu1);
         mCheckBox1.setOnClickListener(mClickListener);
         mCheckBox2 = (CheckBox)v.findViewById(R.id.menu2);
         mCheckBox2.setOnClickListener(mClickListener);
-        
+
         // Make sure fragments start out with correct visibility.
         updateFragmentVisibility();
 
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuSupport.java
index eda8893..29a8e52 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentMenuSupport.java
@@ -41,6 +41,7 @@
 
     // Update fragment visibility when check boxes are changed.
     final OnClickListener mClickListener = new OnClickListener() {
+        @Override
         public void onClick(View v) {
             updateFragmentVisibility();
         }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java
index f413744..14688f3 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java
@@ -57,12 +57,14 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.goto_first);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(0);
             }
         });
         button = (Button)findViewById(R.id.goto_last);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(NUM_ITEMS-1);
             }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentReceiveResultSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentReceiveResultSupport.java
index 4a8e3a3..5f82bef 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentReceiveResultSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentReceiveResultSupport.java
@@ -62,6 +62,7 @@
         private TextView mResults;
 
         private OnClickListener mGetListener = new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 // Start the activity whose result we want to retrieve.  The
                 // result will come back with request code GET_CODE.
@@ -71,6 +72,7 @@
         };
 
         private OnClickListener mIntentSenderListener = new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 // Start the intent sender whose result we want to retrieve.  The
                 // result will come back with request code GET_INTENT_SENDER_CODE.
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentRetainInstanceSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentRetainInstanceSupport.java
index 0ff34dd..8472aa4 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentRetainInstanceSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentRetainInstanceSupport.java
@@ -63,6 +63,7 @@
             // Watch for button clicks.
             Button button = (Button)v.findViewById(R.id.restart);
             button.setOnClickListener(new OnClickListener() {
+                @Override
                 public void onClick(View v) {
                     mWorkFragment.restart();
                 }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackFragmentSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackFragmentSupport.java
index d2eb29a..2c289d7 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackFragmentSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackFragmentSupport.java
@@ -53,18 +53,21 @@
         // Watch for button clicks.
         Button button = (Button)v.findViewById(R.id.new_fragment);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 addFragmentToStack();
             }
         });
         button = (Button)v.findViewById(R.id.delete_fragment);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 getChildFragmentManager().popBackStack();
             }
         });
         button = (Button)v.findViewById(R.id.home);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 // If there is a back stack, pop it all.
                 FragmentManager fm = getChildFragmentManager();
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackSupport.java
index 4115d5e..751b0e1 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStackSupport.java
@@ -43,12 +43,14 @@
         // Watch for button clicks.
         Button button = (Button) findViewById(R.id.new_fragment);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 addFragmentToStack();
             }
         });
         button = (Button) findViewById(R.id.home);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 // If there is a back stack, pop it all.
                 FragmentManager fm = getSupportFragmentManager();
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStatePagerSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStatePagerSupport.java
index 2939b0e..83d9db4 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStatePagerSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentStatePagerSupport.java
@@ -58,12 +58,14 @@
         // Watch for button clicks.
         Button button = (Button)findViewById(R.id.goto_first);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(0);
             }
         });
         button = (Button)findViewById(R.id.goto_last);
         button.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mPager.setCurrentItem(NUM_ITEMS-1);
             }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderThrottleSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderThrottleSupport.java
index 80e237c..a03a690 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderThrottleSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderThrottleSupport.java
@@ -486,6 +486,7 @@
             MainTable.COLUMN_NAME_DATA,
         };
 
+        @Override
         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
             CursorLoader cl = new CursorLoader(getActivity(), MainTable.CONTENT_URI,
                     PROJECTION, null, null, null);
@@ -493,6 +494,7 @@
             return cl;
         }
 
+        @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
             mAdapter.swapCursor(data);
 
@@ -504,6 +506,7 @@
             }
         }
 
+        @Override
         public void onLoaderReset(Loader<Cursor> loader) {
             mAdapter.swapCursor(null);
         }
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/SendResult.java b/samples/Support4Demos/src/com/example/android/supportv4/app/SendResult.java
index 7179505..6495f1f 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/SendResult.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/SendResult.java
@@ -58,6 +58,7 @@
 
     private OnClickListener mCorkyListener = new OnClickListener()
     {
+        @Override
         public void onClick(View v)
         {
             // To send a result, simply call setResult() before your
@@ -69,6 +70,7 @@
 
     private OnClickListener mVioletListener = new OnClickListener()
     {
+        @Override
         public void onClick(View v)
         {
             // To send a result, simply call setResult() before your
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java b/samples/Support4Demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java
index 62a320c..feb5734 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.java
@@ -95,12 +95,14 @@
     }
 
     private OnClickListener mStartListener = new OnClickListener() {
+        @Override
         public void onClick(View v) {
             startService(new Intent(LocalServiceBroadcaster.this, LocalService.class));
         }
     };
 
     private OnClickListener mStopListener = new OnClickListener() {
+        @Override
         public void onClick(View v) {
             stopService(new Intent(LocalServiceBroadcaster.this, LocalService.class));
         }
@@ -136,6 +138,7 @@
             mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
         }
 
+        @Override
         public int onStartCommand(Intent intent, int flags, int startId) {
             // Tell any local interested parties about the start.
             mLocalBroadcastManager.sendBroadcast(new Intent(ACTION_STARTED));
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulController.java b/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulController.java
index bf3b2c0..78f46f2 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulController.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulController.java
@@ -44,6 +44,7 @@
     }
 
     private View.OnClickListener mScheduleListener = new View.OnClickListener() {
+        @Override
         public void onClick(View v) {
             // When the alarm goes off, we want to broadcast an Intent to our
             // BroadcastReceiver.  Here we make an Intent with an explicit class
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
index 546fe8c..c3263ad 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
@@ -237,6 +237,7 @@
     }
 
     private View.OnClickListener mPauseListener = new View.OnClickListener() {
+        @Override
         public void onClick(View v) {
             doPauseResume();
         }
@@ -274,10 +275,12 @@
     // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
     // we will simply apply the updated position without suspending regular updates.
     private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
+        @Override
         public void onStartTrackingTouch(SeekBar bar) {
             mDragging = true;
         }
 
+        @Override
         public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
             if (!fromuser) {
                 // We're not interested in programmatically generated changes to
@@ -292,6 +295,7 @@
                 mCurrentTime.setText(stringForTime( (int) newposition));
         }
 
+        @Override
         public void onStopTrackingTouch(SeekBar bar) {
             mDragging = false;
             updateProgress();
@@ -318,6 +322,7 @@
     }
 
     private View.OnClickListener mRewListener = new View.OnClickListener() {
+        @Override
         public void onClick(View v) {
             long pos = mController.getCurrentPosition();
             pos -= 5000; // milliseconds
@@ -327,6 +332,7 @@
     };
 
     private View.OnClickListener mFfwdListener = new View.OnClickListener() {
+        @Override
         public void onClick(View v) {
             long pos = mController.getCurrentPosition();
             pos += 15000; // milliseconds
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/QueueAdapter.java b/samples/Support4Demos/src/com/example/android/supportv4/media/QueueAdapter.java
index 3d327ff..80c53f6 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/media/QueueAdapter.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/QueueAdapter.java
@@ -52,6 +52,7 @@
         TextView mDescriptionView;
     }
 
+    @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         ViewHolder holder;
 
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/view/CheckableFrameLayout.java b/samples/Support4Demos/src/com/example/android/supportv4/view/CheckableFrameLayout.java
index 1ca8840..6fc6b39 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/view/CheckableFrameLayout.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/view/CheckableFrameLayout.java
@@ -34,15 +34,18 @@
         super(context, attrs);
     }
 
+    @Override
     public void setChecked(boolean checked) {
         mChecked = checked;
         ViewCompat.setBackground(this, checked ? new ColorDrawable(0xff0000a0) : null);
     }
 
+    @Override
     public boolean isChecked() {
         return mChecked;
     }
 
+    @Override
     public void toggle() {
         setChecked(!mChecked);
     }
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java
index e2ae88c..17f34243 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java
@@ -115,6 +115,7 @@
         getDelegate().onDestroy();
     }
 
+    @Override
     public void invalidateOptionsMenu() {
         getDelegate().invalidateOptionsMenu();
     }
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java
index 1191be0..f086bdf 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/GridLayoutManagerActivity.java
@@ -110,6 +110,7 @@
         }
     }
 
+    @Override
     protected RecyclerView.Adapter createAdapter() {
         mAdapter = new SimpleStringAdapter(this, Cheeses.sCheeseStrings) {
             @Override
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/NestedRecyclerViewActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/NestedRecyclerViewActivity.java
index 88b9992..dff2940 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/widget/NestedRecyclerViewActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/NestedRecyclerViewActivity.java
@@ -146,6 +146,7 @@
         }
     }
 
+    @Override
     protected RecyclerView.Adapter createAdapter() {
         return new OuterAdapter(Cheeses.sCheeseStrings);
     }
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/StableIdActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/StableIdActivity.java
index 8932704..70216f5 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/widget/StableIdActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/StableIdActivity.java
@@ -63,6 +63,7 @@
         return new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
     }
 
+    @Override
     protected RecyclerView.Adapter createAdapter() {
         return new StableIdAdapter(Cheeses.sCheeseStrings);
     }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java
index 6c1ce85..2f0e861 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java
@@ -106,6 +106,7 @@
 
         // simulates in a real world use case  data being loaded two seconds later
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 setupRows();
                 loadData();
@@ -289,6 +290,7 @@
             setAdapter(adapter);
             // simulates late data loading:
             new Handler().postDelayed(new Runnable() {
+                @Override
                 public void run() {
                     loadFragmentData();
                 }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java
index fa1425b..c78319d 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java
@@ -109,6 +109,7 @@
 
         // simulates in a real world use case  data being loaded two seconds later
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 setupRows();
                 loadData();
@@ -292,6 +293,7 @@
             setAdapter(adapter);
             // simulates late data loading:
             new Handler().postDelayed(new Runnable() {
+                @Override
                 public void run() {
                     loadFragmentData();
                 }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java
index 56acc05..bb282f4 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsFragment.java
@@ -183,6 +183,7 @@
         }
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 final Context context = getActivity();
                 DetailsOverviewRow dor = new DetailsOverviewRow(mPhotoItem.getTitle());
@@ -198,6 +199,7 @@
         }, TIME_TO_LOAD_OVERVIEW_ROW_MS);
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < NUM_ROWS; ++i) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java
index e58e2e7..8e7a127 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java
@@ -186,6 +186,7 @@
         }
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 final Context context = getActivity();
                 DetailsOverviewRow dor = new DetailsOverviewRow(mPhotoItem.getTitle());
@@ -201,6 +202,7 @@
         }, TIME_TO_LOAD_OVERVIEW_ROW_MS);
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < NUM_ROWS; ++i) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java
index a311338..e7831d6 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java
@@ -376,8 +376,10 @@
             mExpandPaymentListInOnCreateView = true;
         }
 
+        @Override
         public GuidedActionsStylist onCreateActionsStylist() {
             return new GuidedActionsStylist() {
+                @Override
                 protected void setupImeOptions(GuidedActionsStylist.ViewHolder vh,
                         GuidedAction action) {
                     if (action.getId() == PASSWORD) {
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java
index 0cd6edd..717fccd 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java
@@ -379,8 +379,10 @@
             mExpandPaymentListInOnCreateView = true;
         }
 
+        @Override
         public GuidedActionsStylist onCreateActionsStylist() {
             return new GuidedActionsStylist() {
+                @Override
                 protected void setupImeOptions(GuidedActionsStylist.ViewHolder vh,
                         GuidedAction action) {
                     if (action.getId() == PASSWORD) {
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java
index 9b801dc..3807de1 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java
@@ -228,6 +228,7 @@
         }
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (TEST_OVERVIEW_ROW_ON_SECOND) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
@@ -259,6 +260,7 @@
         }, TIME_TO_LOAD_OVERVIEW_ROW_MS);
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < NUM_ROWS; ++i) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java
index 77ce368..697b1e0 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java
@@ -231,6 +231,7 @@
         }
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (TEST_OVERVIEW_ROW_ON_SECOND) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
@@ -262,6 +263,7 @@
         }, TIME_TO_LOAD_OVERVIEW_ROW_MS);
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < NUM_ROWS; ++i) {
                     ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java
index 91ecd62..2687d70 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java
@@ -59,6 +59,7 @@
     private PlaybackControlGlue mGlue;
     private ListRowPresenter mListRowPresenter;
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
index 8e9dde2..21086d9 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
@@ -84,6 +84,7 @@
                 }
     };
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
index f2de9a9..879ee69 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
@@ -87,6 +87,7 @@
                 }
     };
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java
index 64effab..d83f917 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java
@@ -62,6 +62,7 @@
     private PlaybackControlGlue mGlue;
     private ListRowPresenter mListRowPresenter;
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java
index 0302f68..40883bb 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/StringPresenter.java
@@ -23,6 +23,7 @@
 public class StringPresenter extends Presenter {
     private static final String TAG = "StringPresenter";
 
+    @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent) {
         Log.d(TAG, "onCreateViewHolder");
         final Context context = parent.getContext();
@@ -34,12 +35,14 @@
         return new ViewHolder(tv);
     }
 
+    @Override
     public void onBindViewHolder(ViewHolder viewHolder, Object item) {
         Log.d(TAG, "onBindViewHolder for " + item.toString());
         ((TextView) viewHolder.view).setText(item.toString());
     }
 
+    @Override
     public void onUnbindViewHolder(ViewHolder viewHolder) {
-        Log.d(TAG, "onUnbindViewHolder"); 
+        Log.d(TAG, "onUnbindViewHolder");
     }
 }
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java
index 68de793..f7b8c8c 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java
@@ -65,6 +65,7 @@
         }
         // simulates in a real world use case  data being loaded two seconds later
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 loadData();
                 startEntranceTransition();
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java
index e8f0cc8..6843e55 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java
@@ -68,6 +68,7 @@
         }
         // simulates in a real world use case  data being loaded two seconds later
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 loadData();
                 startEntranceTransition();
diff --git a/samples/SupportLeanbackJank/build.gradle b/samples/SupportLeanbackJank/build.gradle
index 976dc9b..42adb9a 100644
--- a/samples/SupportLeanbackJank/build.gradle
+++ b/samples/SupportLeanbackJank/build.gradle
@@ -21,7 +21,7 @@
     }
 
     lintOptions {
-        abortOnError false
+        abortOnError true
     }
 
     compileOptions {
diff --git a/samples/SupportLeanbackJank/res/values-v21/styles.xml b/samples/SupportLeanbackJank/res/values-v21/styles.xml
new file mode 100644
index 0000000..ef7efe9
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/values-v21/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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
+  -->
+
+<resources>
+    <style name="JankApp" parent="Theme.Leanback">
+        <item name="android:colorPrimary">@color/jank_yellow</item>
+        <item name="android:windowAllowReturnTransitionOverlap">true</item>
+        <item name="android:windowAllowEnterTransitionOverlap">true</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/res/values/styles.xml b/samples/SupportLeanbackJank/res/values/styles.xml
index ef7efe9..ba3a5de 100644
--- a/samples/SupportLeanbackJank/res/values/styles.xml
+++ b/samples/SupportLeanbackJank/res/values/styles.xml
@@ -17,8 +17,5 @@
 
 <resources>
     <style name="JankApp" parent="Theme.Leanback">
-        <item name="android:colorPrimary">@color/jank_yellow</item>
-        <item name="android:windowAllowReturnTransitionOverlap">true</item>
-        <item name="android:windowAllowEnterTransitionOverlap">true</item>
     </style>
 </resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java
index a9e0dd5..909da45 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java
@@ -131,7 +131,8 @@
 
         canvas.drawText(string, width / 2, (height + rect.height()) / 2, paint);
 
-        try (FileOutputStream outputStream = new FileOutputStream(file)) {
+        try {
+            FileOutputStream outputStream = new FileOutputStream(file);
             bitmap.compress(CompressFormat.JPEG, 90, outputStream);
         } catch (IOException e) {
             Log.e(TAG, "Cannot write image to file: " + file, e);
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
index 564ff92..d301c4e 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
@@ -18,6 +18,7 @@
 
 import android.support.v17.leanback.widget.ImageCardView;
 import android.support.v17.leanback.widget.Presenter;
+import android.support.v4.content.res.ResourcesCompat;
 import android.view.ViewGroup;
 
 import com.bumptech.glide.Glide;
@@ -37,8 +38,10 @@
 
     @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        mDefaultBackgroundColor = parent.getResources().getColor(R.color.jank_blue, null);
-        mSelectedBackgroundColor = parent.getResources().getColor(R.color.jank_red, null);
+        mDefaultBackgroundColor =
+                ResourcesCompat.getColor(parent.getResources(), R.color.jank_blue, null);
+        mSelectedBackgroundColor =
+                ResourcesCompat.getColor(parent.getResources(), R.color.jank_red, null);
 
         ImageCardView cardView = new ImageCardView(parent.getContext()) {
             @Override
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java
index ff99a9b..3374f5e 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java
@@ -19,6 +19,7 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.support.v17.leanback.widget.Presenter;
+import android.support.v4.content.res.ResourcesCompat;
 import android.view.Gravity;
 import android.view.ViewGroup;
 import android.widget.TextView;
@@ -38,7 +39,8 @@
         view.setLayoutParams(new ViewGroup.LayoutParams(width, height));
         view.setFocusable(true);
         view.setFocusableInTouchMode(true);
-        view.setBackgroundColor(parent.getResources().getColor(R.color.jank_yellow, null));
+        view.setBackgroundColor(
+                ResourcesCompat.getColor(parent.getResources(), R.color.jank_yellow, null));
         view.setTextColor(Color.WHITE);
         view.setGravity(Gravity.CENTER);
         return new ViewHolder(view);
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java
index 9740088..6d6b36f 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java
@@ -22,6 +22,7 @@
 import android.support.v17.leanback.widget.ListRow;
 import android.support.v17.leanback.widget.Presenter;
 import android.support.v17.leanback.widget.RowHeaderPresenter;
+import android.support.v4.content.res.ResourcesCompat;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -53,7 +54,8 @@
         rootView.setFocusable(true);
 
         ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
-        Drawable icon = rootView.getResources().getDrawable(R.drawable.android_header, null);
+        Drawable icon = ResourcesCompat.getDrawable(
+                rootView.getResources(), R.drawable.android_header, null);
         iconView.setImageDrawable(icon);
 
         TextView label = (TextView) rootView.findViewById(R.id.header_label);
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
index 5cbff96..42abf3e 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
@@ -27,6 +27,7 @@
 import android.support.v17.leanback.widget.ListRowPresenter;
 import android.support.v17.leanback.widget.Presenter;
 import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v4.content.res.ResourcesCompat;
 
 import com.google.android.leanbackjank.IntentDefaults;
 import com.google.android.leanbackjank.IntentKeys;
@@ -90,9 +91,9 @@
             } else if (whichVideo == IntentKeys.VIDEO_480P_60FPS) {
                 resource = R.raw.bbb_480p;
             }
-            Uri uri = Uri.parse("android.resource://" + getContext().getPackageName() + "/"
+            Uri uri = Uri.parse("android.resource://" + getActivity().getPackageName() + "/"
                     + resource);
-            Intent videoIntent = new Intent(Intent.ACTION_VIEW, uri, getContext(),
+            Intent videoIntent = new Intent(Intent.ACTION_VIEW, uri, getActivity(),
                     VideoActivity.class);
             startActivity(videoIntent);
         }
@@ -102,19 +103,21 @@
         mBackgroundManager = BackgroundManager.getInstance(getActivity());
         mBackgroundManager.attach(getActivity().getWindow());
         mBackgroundManager.setDrawable(
-                getResources().getDrawable(R.drawable.default_background, null));
+                ResourcesCompat.getDrawable(getResources(), R.drawable.default_background, null));
     }
 
     private void setupUIElements() {
-        setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.app_banner, null));
+        setBadgeDrawable(ResourcesCompat.getDrawable(
+                getActivity().getResources(), R.drawable.app_banner, null));
         // Badge, when set, takes precedent over title
         setTitle(getString(R.string.browse_title));
         setHeadersState(HEADERS_ENABLED);
         setHeadersTransitionOnBackEnabled(true);
         // set headers background color
-        setBrandColor(getResources().getColor(R.color.jank_yellow));
+        setBrandColor(ResourcesCompat.getColor(getResources(), R.color.jank_yellow, null));
         // set search icon color
-        setSearchAffordanceColor(getResources().getColor(R.color.search_opaque));
+        setSearchAffordanceColor(
+                ResourcesCompat.getColor(getResources(), R.color.search_opaque, null));
 
         setHeaderPresenterSelector(new PresenterSelector() {
             @Override
@@ -130,7 +133,7 @@
         listRowPresenter.setShadowEnabled(!disableShadows);
         mRowsAdapter = new ArrayObjectAdapter(listRowPresenter);
         HashMap<String, List<VideoInfo>> data = VideoProvider.buildMedia(categoryCount,
-                entriesPerCat, cardWidth, cardHeight, getContext(), useSingleBitmap);
+                entriesPerCat, cardWidth, cardHeight, getActivity(), useSingleBitmap);
         CardPresenter cardPresenter = new CardPresenter(cardWidth, cardHeight);
 
         int i = 0;
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java
index f026cc2..90c8552 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java
@@ -21,6 +21,7 @@
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnPreparedListener;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.view.Window;
 import android.view.WindowManager;
@@ -48,7 +49,9 @@
         setContentView(mVideoView);
 
         if (checkIntent(getIntent())) {
-            enterPictureInPictureMode();
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                enterPictureInPictureMode();
+            }
         }
     }
 
diff --git a/samples/SupportPreferenceDemos/src/com/example/android/supportpreference/FragmentSupportPreferencesLeanback.java b/samples/SupportPreferenceDemos/src/com/example/android/supportpreference/FragmentSupportPreferencesLeanback.java
index f7babfb..eb9a4c0 100644
--- a/samples/SupportPreferenceDemos/src/com/example/android/supportpreference/FragmentSupportPreferencesLeanback.java
+++ b/samples/SupportPreferenceDemos/src/com/example/android/supportpreference/FragmentSupportPreferencesLeanback.java
@@ -16,6 +16,7 @@
 
 package com.example.android.supportpreference;
 
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.Fragment;
 import android.os.Bundle;
@@ -26,6 +27,7 @@
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
+@TargetApi(17)
 public class FragmentSupportPreferencesLeanback extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/samples/SupportTransitionDemos/Android.mk b/samples/SupportTransitionDemos/Android.mk
index 6ebc7af..e822a0a 100644
--- a/samples/SupportTransitionDemos/Android.mk
+++ b/samples/SupportTransitionDemos/Android.mk
@@ -29,6 +29,6 @@
         android-support-v4 \
         android-support-v7-appcompat \
         android-support-transition
-LOCAL_AAPT_FLAGS := --no-version-vectors
+LOCAL_AAPT_FLAGS := --no-version-vectors --no-version-transitions
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 include $(BUILD_PACKAGE)
diff --git a/samples/SupportTransitionDemos/AndroidManifest.xml b/samples/SupportTransitionDemos/AndroidManifest.xml
index 4028f47..083f898 100644
--- a/samples/SupportTransitionDemos/AndroidManifest.xml
+++ b/samples/SupportTransitionDemos/AndroidManifest.xml
@@ -63,5 +63,14 @@
                 <category android:name="com.example.android.support.transition.SAMPLE_CODE" />
             </intent-filter>
         </activity>
+
+        <activity android:name=".widget.ArcMotionUsage"
+                  android:label="@string/arcMotion"
+                  android:theme="@style/Theme.Transition">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.example.android.support.transition.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/samples/SupportTransitionDemos/build.gradle b/samples/SupportTransitionDemos/build.gradle
index a80ebcb..4025f23 100644
--- a/samples/SupportTransitionDemos/build.gradle
+++ b/samples/SupportTransitionDemos/build.gradle
@@ -27,5 +27,9 @@
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
     }
+
+    aaptOptions {
+        additionalParameters "--no-version-transitions"
+    }
 }
 
diff --git a/samples/SupportTransitionDemos/res/layout/arc_motion.xml b/samples/SupportTransitionDemos/res/layout/arc_motion.xml
new file mode 100644
index 0000000..8dccd0a
--- /dev/null
+++ b/samples/SupportTransitionDemos/res/layout/arc_motion.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <Button
+        android:id="@+id/move"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/move"/>
+
+    <FrameLayout
+        android:id="@+id/root"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:padding="64dp">
+
+        <View
+            android:id="@+id/target"
+            android:layout_width="64dp"
+            android:layout_height="64dp"
+            android:layout_gravity="end|bottom"
+            android:background="#00f"/>
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/samples/SupportTransitionDemos/res/values/strings.xml b/samples/SupportTransitionDemos/res/values/strings.xml
index 09319e6..de69ee1 100644
--- a/samples/SupportTransitionDemos/res/values/strings.xml
+++ b/samples/SupportTransitionDemos/res/values/strings.xml
@@ -19,7 +19,9 @@
     <string name="scene">Scene</string>
     <string name="custom">Custom Transition</string>
     <string name="beginDelayed">Begin Delayed Transition</string>
+    <string name="arcMotion">Arc Motion</string>
     <string name="toggle">Toggle</string>
     <string name="begin">Begin</string>
     <string name="hello_world">Hello, world!</string>
+    <string name="move">Move</string>
 </resources>
diff --git a/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ArcMotionUsage.java b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ArcMotionUsage.java
new file mode 100644
index 0000000..52b53f4
--- /dev/null
+++ b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ArcMotionUsage.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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 com.example.android.support.transition.widget;
+
+import android.os.Bundle;
+import android.support.transition.ArcMotion;
+import android.support.transition.ChangeBounds;
+import android.support.transition.Transition;
+import android.support.transition.TransitionManager;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.example.android.support.transition.R;
+
+/**
+ * This demonstrates usage of {@link ArcMotion}.
+ */
+public class ArcMotionUsage extends TransitionUsageBase {
+
+    private FrameLayout mRoot;
+    private View mTarget;
+    private Transition mTransition;
+
+    @Override
+    int getLayoutResId() {
+        return R.layout.arc_motion;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mRoot = (FrameLayout) findViewById(R.id.root);
+        mTarget = findViewById(R.id.target);
+        mTransition = new ChangeBounds();
+        mTransition.setPathMotion(new ArcMotion());
+        mTransition.setInterpolator(new FastOutSlowInInterpolator());
+        mTransition.setDuration(500);
+        findViewById(R.id.move).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                TransitionManager.beginDelayedTransition(mRoot, mTransition);
+                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mTarget.getLayoutParams();
+                if ((lp.gravity & Gravity.START) == Gravity.START) {
+                    lp.gravity = Gravity.END | Gravity.BOTTOM;
+                } else {
+                    lp.gravity = Gravity.START | Gravity.TOP;
+                }
+                mTarget.setLayoutParams(lp);
+            }
+        });
+    }
+
+}
diff --git a/samples/SupportVectorDrawable/animated/AndroidManifest.xml b/samples/SupportVectorDrawable/animated/AndroidManifest.xml
deleted file mode 100644
index 09a5dbb..0000000
--- a/samples/SupportVectorDrawable/animated/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.support.vectordrawable" >
-
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23"/>
-
-    <application android:icon="@drawable/app_sample_code" android:label="AnimatedVectorDrawableCompatTest" >
-        <activity android:name="com.example.android.support.vectordrawable.app.AnimatedButtonBackground" />
-        <intent-filter>
-            <action android:name="android.intent.action.MAIN" />
-
-            <category android:name="android.intent.category.LAUNCHER" />
-        </intent-filter>
-    </application>
-
-</manifest>
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/app_sample_code.png b/samples/SupportVectorDrawable/animated/res/drawable/app_sample_code.png
deleted file mode 100755
index 66a1984..0000000
--- a/samples/SupportVectorDrawable/animated/res/drawable/app_sample_code.png
+++ /dev/null
Binary files differ
diff --git a/samples/SupportVectorDrawable/animated/res/values/strings.xml b/samples/SupportVectorDrawable/animated/res/values/strings.xml
deleted file mode 100644
index c5451c8..0000000
--- a/samples/SupportVectorDrawable/animated/res/values/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 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.
--->
-
-<resources>
-
-    <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
-    <string name="triangle"> "M300,70 l 0,-70 70,70 0,0   -70,70z"</string>
-    <string name="rectangle">"M300,70 l 0,-70 70,0  0,140 -70,0 z"</string>
-    <string name="rectangle2">"M300,70 l 0,-70 70,0  0,70z M300,70  l 70,0 0,70 -70,0z"</string>
-    <string name="equal2">    "M300,35 l 0,-35 70,0  0,35z M300,105 l 70,0 0,35 -70,0z"</string>
-    <string name="round_box">"m2.10001,-6c-1.9551,0 -0.5,0.02499 -2.10001,0.02499c-1.575,0 0.0031,-0.02499 -1.95,-0.02499c-2.543,0 -4,2.2816 -4,4.85001c0,3.52929 0.25,6.25 5.95,6.25c5.7,0 6,-2.72071 6,-6.25c0,-2.56841 -1.35699,-4.85001 -3.89999,-4.85001"</string>
-    <string name="heart">    "m4.5,-7c-1.95509,0 -3.83009,1.26759 -4.5,3c-0.66991,-1.73241 -2.54691,-3 -4.5,-3c-2.543,0 -4.5,1.93159 -4.5,4.5c0,3.5293 3.793,6.2578 9,11.5c5.207,-5.2422 9,-7.9707 9,-11.5c0,-2.56841 -1.957,-4.5 -4.5,-4.5"</string>
-    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
-</resources>
\ No newline at end of file
diff --git a/samples/SupportVectorDrawable/animated/rundemo.sh b/samples/SupportVectorDrawable/animated/rundemo.sh
deleted file mode 100755
index e5972f7..0000000
--- a/samples/SupportVectorDrawable/animated/rundemo.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-. $ANDROID_BUILD_TOP/build/envsetup.sh && \
-mmm -j20 . && \
-adb install -r $OUT/data/app/SupportAnimatedVectorDrawable/SupportAnimatedVectorDrawable.apk && \
-adb shell am start -n com.example.android.support.vectordrawable/com.example.android.support.vectordrawable.app.AnimatedButtonBackground
-
-
diff --git a/samples/SupportVectorDrawable/static/Android.mk b/samples/SupportVectorDrawable/static/Android.mk
deleted file mode 100644
index bdc102a..0000000
--- a/samples/SupportVectorDrawable/static/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_MODULE_TAGS := samples tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SupportVectorDrawable
-
-LOCAL_STATIC_ANDROID_LIBRARIES := android-support-vectordrawable android-support-v4
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_MIN_SDK_VERSION := 7
-
-LOCAL_AAPT_FLAGS += --no-version-vectors
-
-include $(BUILD_PACKAGE)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/SupportVectorDrawable/static/AndroidManifest.xml b/samples/SupportVectorDrawable/static/AndroidManifest.xml
deleted file mode 100644
index 53fc9c2..0000000
--- a/samples/SupportVectorDrawable/static/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.support.vectordrawable" >
-
-    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="23"/>
-
-    <application android:icon="@drawable/app_sample_code" android:label="VectorDrawableCompatTest" >
-        <activity android:name=".app.SimpleButtonBackground" />
-
-        <intent-filter>
-            <action android:name="android.intent.action.MAIN" />
-
-            <category android:name="android.intent.category.LAUNCHER" />
-        </intent-filter>
-    </application>
-
-</manifest>
diff --git a/samples/SupportVectorDrawable/static/rundemo.sh b/samples/SupportVectorDrawable/static/rundemo.sh
deleted file mode 100755
index 2695b53..0000000
--- a/samples/SupportVectorDrawable/static/rundemo.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-. $ANDROID_BUILD_TOP/build/envsetup.sh && \
-mmm -j20 . && \
-adb install -r $OUT/data/app/SupportVectorDrawable/SupportVectorDrawable.apk && \
-adb shell am start -n com.example.android.support.vectordrawable/com.example.android.support.vectordrawable.app.SimpleButtonBackground
-
-
diff --git a/samples/SupportVectorDrawable/animated/Android.mk b/samples/SupportVectorDrawableDemos/Android.mk
similarity index 88%
rename from samples/SupportVectorDrawable/animated/Android.mk
rename to samples/SupportVectorDrawableDemos/Android.mk
index ae01691..376f841 100644
--- a/samples/SupportVectorDrawable/animated/Android.mk
+++ b/samples/SupportVectorDrawableDemos/Android.mk
@@ -18,17 +18,18 @@
 
 LOCAL_USE_AAPT2 := true
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := samples tests
 
 LOCAL_SDK_VERSION := current
 
-LOCAL_MIN_SDK_VERSION := 11
+LOCAL_MIN_SDK_VERSION := 14
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := SupportAnimatedVectorDrawable
+LOCAL_PACKAGE_NAME := SupportVectorDrawableDemos
 
 LOCAL_STATIC_ANDROID_LIBRARIES := \
+        android-support-v7-appcompat \
         android-support-animatedvectordrawable \
         android-support-vectordrawable \
         android-support-v4
diff --git a/samples/SupportVectorDrawableDemos/AndroidManifest.xml b/samples/SupportVectorDrawableDemos/AndroidManifest.xml
new file mode 100644
index 0000000..1de3a5f
--- /dev/null
+++ b/samples/SupportVectorDrawableDemos/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.support.vectordrawable" >
+
+    <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
+
+    <application android:icon="@drawable/app_sample_code" android:label="SupportVectorDrawableDemos" >
+        <activity android:name="com.example.android.support.vectordrawable.app.SupportVectorDrawableDemos">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.example.android.support.vectordrawable.app.SimpleAnimatedVectorDrawable"
+                  android:label="SimpleAnimatedVectorDrawable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.example.android.support.vectordrawable.app.SimpleStaticVectorDrawable"
+                  android:label="SimpleVectorDrawable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.example.android.support.vectordrawable.app.AVDCListenerDemo"
+                  android:label="AnimatedVectorDrawableCompatListener"
+                  android:theme="@style/Theme.AppCompat.Light">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/SupportVectorDrawableDemos/build.gradle b/samples/SupportVectorDrawableDemos/build.gradle
new file mode 100644
index 0000000..f58f402
--- /dev/null
+++ b/samples/SupportVectorDrawableDemos/build.gradle
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+apply plugin: 'com.android.application'
+
+dependencies {
+    compile project(':support-vector-drawable')
+    compile project(':support-animated-vector-drawable')
+    compile project(':support-appcompat-v7')
+}
+
+android {
+    compileSdkVersion project.ext.currentSdk
+
+    defaultConfig {
+        minSdkVersion 14
+        vectorDrawables.useSupportLibrary = true
+    }
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDirs = ['src']
+        main.aidl.srcDirs = ['src']
+        main.res.srcDirs = ['res']
+    }
+
+    lintOptions {
+        checkReleaseBuilds false
+        abortOnError false
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+}
+
diff --git a/samples/SupportVectorDrawable/animated/res/anim/alpha_animation_progress_bar.xml b/samples/SupportVectorDrawableDemos/res/anim/alpha_animation_progress_bar.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/anim/alpha_animation_progress_bar.xml
rename to samples/SupportVectorDrawableDemos/res/anim/alpha_animation_progress_bar.xml
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/samples/SupportVectorDrawableDemos/res/anim/animation_grouping_1_01.xml
similarity index 75%
rename from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
rename to samples/SupportVectorDrawableDemos/res/anim/animation_grouping_1_01.xml
index 36c297f..9a89d63 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/samples/SupportVectorDrawableDemos/res/anim/animation_grouping_1_01.xml
@@ -16,7 +16,8 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+                android:duration="3300"
+                android:interpolator="@android:anim/linear_interpolator"
+                android:propertyName="rotation"
+                android:valueFrom="0"
+                android:valueTo="450"/>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/trim_path_animation_progress_bar.xml b/samples/SupportVectorDrawableDemos/res/anim/trim_path_animation_progress_bar.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/anim/trim_path_animation_progress_bar.xml
rename to samples/SupportVectorDrawableDemos/res/anim/trim_path_animation_progress_bar.xml
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/animation_vector_drawable_grouping_1.xml b/samples/SupportVectorDrawableDemos/res/drawable/animation_vector_drawable_grouping_1.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/drawable/animation_vector_drawable_grouping_1.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/animation_vector_drawable_grouping_1.xml
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/animation_vector_progress_bar.xml b/samples/SupportVectorDrawableDemos/res/drawable/animation_vector_progress_bar.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/drawable/animation_vector_progress_bar.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/animation_vector_progress_bar.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/app_sample_code.png b/samples/SupportVectorDrawableDemos/res/drawable/app_sample_code.png
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/app_sample_code.png
rename to samples/SupportVectorDrawableDemos/res/drawable/app_sample_code.png
Binary files differ
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/btn_radio_on_to_off_bundle.xml b/samples/SupportVectorDrawableDemos/res/drawable/btn_radio_on_to_off_bundle.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/drawable/btn_radio_on_to_off_bundle.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/btn_radio_on_to_off_bundle.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable01.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable01.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable01.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable01.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable02.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable02.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable02.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable02.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable03.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable03.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable03.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable03.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable04.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable04.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable04.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable04.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable05.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable05.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable05.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable05.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable06.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable06.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable06.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable06.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable07.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable07.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable07.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable07.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable08.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable08.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable08.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable08.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable09.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable09.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable09.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable09.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable10.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable10.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable10.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable10.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable11.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable11.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable11.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable11.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable12.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable12.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable12.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable12.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable13.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable13.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable13.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable13.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable14.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable14.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable14.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable14.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable15.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable15.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable15.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable15.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable16.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable16.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable16.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable16.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable17.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable17.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable17.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable17.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable18.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable18.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable18.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable18.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable19.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable19.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable19.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable19.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable20.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable20.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable20.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable20.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable21.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable21.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable21.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable21.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable22.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable22.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable22.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable22.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable23.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable23.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable23.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable23.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable24.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable24.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable24.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable24.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable25.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable25.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable25.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable25.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable26.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable26.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable26.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable26.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable27.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable27.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable27.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable27.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable28.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable28.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable28.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable28.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable29.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable29.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable29.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable29.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable30.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable30.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable30.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable30.xml
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/vector_drawable_grouping_1.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_grouping_1.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/drawable/vector_drawable_grouping_1.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_grouping_1.xml
diff --git a/samples/SupportVectorDrawable/animated/res/drawable/vector_drawable_progress_bar.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_progress_bar.xml
similarity index 100%
rename from samples/SupportVectorDrawable/animated/res/drawable/vector_drawable_progress_bar.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_progress_bar.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale0.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale0.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale0.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale0.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale1.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale1.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale1.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale1.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale2.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale2.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale2.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale2.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale3.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale3.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_drawable_scale3.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_drawable_scale3.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_test01.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_test01.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_test01.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_test01.xml
diff --git a/samples/SupportVectorDrawable/static/res/drawable/vector_test02.xml b/samples/SupportVectorDrawableDemos/res/drawable/vector_test02.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/drawable/vector_test02.xml
rename to samples/SupportVectorDrawableDemos/res/drawable/vector_test02.xml
diff --git a/samples/SupportVectorDrawableDemos/res/layout/avdc_listener.xml b/samples/SupportVectorDrawableDemos/res/layout/avdc_listener.xml
new file mode 100644
index 0000000..279a7cf
--- /dev/null
+++ b/samples/SupportVectorDrawableDemos/res/layout/avdc_listener.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:app="http://schemas.android.com/apk/res-auto"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent" android:weightSum="1">
+
+    <android.support.v7.widget.AppCompatImageView
+        app:srcCompat="@drawable/animation_vector_drawable_grouping_1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/imageView"/>
+    <TextView
+        android:text="TextView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/textView"/>
+    <TextView
+        android:text="TextView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/textView2"/>
+    <android.support.v7.widget.AppCompatImageView
+        app:srcCompat="@drawable/btn_radio_on_to_off_bundle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/imageView2"/>
+    <TextView
+        android:text="TextView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/textView3"/>
+    <TextView
+        android:text="TextView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:id="@+id/textView4"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/SupportVectorDrawable/static/res/raw/vector_drawable01.xml b/samples/SupportVectorDrawableDemos/res/raw/vector_drawable01.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/raw/vector_drawable01.xml
rename to samples/SupportVectorDrawableDemos/res/raw/vector_drawable01.xml
diff --git a/samples/SupportVectorDrawable/static/res/values/colors.xml b/samples/SupportVectorDrawableDemos/res/values/colors.xml
similarity index 100%
rename from samples/SupportVectorDrawable/static/res/values/colors.xml
rename to samples/SupportVectorDrawableDemos/res/values/colors.xml
diff --git a/samples/SupportVectorDrawable/static/res/values/strings.xml b/samples/SupportVectorDrawableDemos/res/values/strings.xml
similarity index 99%
rename from samples/SupportVectorDrawable/static/res/values/strings.xml
rename to samples/SupportVectorDrawableDemos/res/values/strings.xml
index 065e7d9..a59ad14 100644
--- a/samples/SupportVectorDrawable/static/res/values/strings.xml
+++ b/samples/SupportVectorDrawableDemos/res/values/strings.xml
@@ -16,7 +16,6 @@
 -->
 
 <resources>
-
     <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
     <string name="triangle"> "M300,70 l 0,-70 70,70 0,0   -70,70z"</string>
     <string name="rectangle">"M300,70 l 0,-70 70,0  0,140 -70,0 z"</string>
@@ -26,4 +25,4 @@
     <string name="heart">    "m4.5,-7c-1.95509,0 -3.83009,1.26759 -4.5,3c-0.66991,-1.73241 -2.54691,-3 -4.5,-3c-2.543,0 -4.5,1.93159 -4.5,4.5c0,3.5293 3.793,6.2578 9,11.5c5.207,-5.2422 9,-7.9707 9,-11.5c0,-2.56841 -1.957,-4.5 -4.5,-4.5"</string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
     <string name="triangle100">"M 100, 0 l 0, 100, -100, 0 z"</string>
-</resources>
+</resources>
\ No newline at end of file
diff --git a/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/AVDCListenerDemo.java b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/AVDCListenerDemo.java
new file mode 100644
index 0000000..f228a43
--- /dev/null
+++ b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/AVDCListenerDemo.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2017 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 com.example.android.support.vectordrawable.app;
+
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.graphics.drawable.Animatable2Compat;
+import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.AppCompatImageView;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+
+import com.example.android.support.vectordrawable.R;
+
+/**
+ * A demo for AnimatedVectorDrawableCompat's listener support.
+ */
+public class AVDCListenerDemo extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.avdc_listener);
+        final AppCompatImageView imageView1 = (AppCompatImageView) findViewById(R.id.imageView);
+        final AppCompatImageView imageView2 = (AppCompatImageView) findViewById(R.id.imageView2);
+
+        final TextView textView1 = (TextView) findViewById(R.id.textView);
+        textView1.setText("Should show start / end for first AVD");
+        final TextView textView2 = (TextView) findViewById(R.id.textView2);
+        textView2.setText("Not affected by AVD, b/c removed after register");
+        final TextView textView3 = (TextView) findViewById(R.id.textView3);
+        textView3.setText("Should show start / end for second AVD");
+        final TextView textView4 = (TextView) findViewById(R.id.textView4);
+        textView4.setText("Not affected by AVD, b/c unregistered after register");
+
+        final Drawable drawable1 = imageView1.getDrawable();
+        final Drawable drawable2 = imageView2.getDrawable();
+
+        Animatable2Compat.AnimationCallback textView1Callback = new
+                Animatable2Compat.AnimationCallback() {
+                    @Override
+                    public void onAnimationStart(Drawable drawable) {
+                        textView1.setText("AVD 1 started");
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        textView1.setText("AVD 1 Ended");
+                    }
+                };
+        Animatable2Compat.AnimationCallback textView2Callback = new
+                Animatable2Compat.AnimationCallback() {
+                    @Override
+                    public void onAnimationStart(Drawable drawable) {
+                        textView2.setText("AVD 1 started");
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        textView2.setText("AVD 1 Ended");
+                    }
+                };
+        AnimatedVectorDrawableCompat.registerAnimationCallback(drawable1, textView1Callback);
+        AnimatedVectorDrawableCompat.registerAnimationCallback(drawable1, textView2Callback);
+        AnimatedVectorDrawableCompat.clearAnimationCallbacks(drawable1);
+        AnimatedVectorDrawableCompat.registerAnimationCallback(drawable1, textView1Callback);
+
+        AnimatedVectorDrawableCompat.registerAnimationCallback(drawable2,
+                new Animatable2Compat.AnimationCallback() {
+                    @Override
+                    public void onAnimationStart(Drawable drawable) {
+                        textView3.setText("AVD 2 started");
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        textView3.setText("AVD 2 Ended");
+                    }
+                });
+
+        Animatable2Compat.AnimationCallback textView4Callback = new
+                Animatable2Compat.AnimationCallback() {
+                    @Override
+                    public void onAnimationStart(Drawable drawable) {
+                        textView4.setText("AVD 2 started");
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        textView4.setText("AVD 2 Ended");
+                    }
+                };
+
+        AnimatedVectorDrawableCompat.registerAnimationCallback(drawable2, textView4Callback);
+        AnimatedVectorDrawableCompat.unregisterAnimationCallback(drawable2, textView4Callback);
+
+        // Touch the imageView will run the AVD.
+        imageView1.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (!((Animatable) drawable1).isRunning()) {
+                    ((Animatable) drawable1).start();
+                }
+                return true;
+            }
+        });
+
+        imageView2.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (!((Animatable) drawable2).isRunning()) {
+                    ((Animatable) drawable2).start();
+                }
+                return true;
+            }
+        });
+    }
+}
diff --git a/samples/SupportVectorDrawable/animated/src/com/example/android/support/vectordrawable/app/AnimatedButtonBackground.java b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleAnimatedVectorDrawable.java
similarity index 79%
rename from samples/SupportVectorDrawable/animated/src/com/example/android/support/vectordrawable/app/AnimatedButtonBackground.java
rename to samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleAnimatedVectorDrawable.java
index d8381d1..76f6770 100644
--- a/samples/SupportVectorDrawable/animated/src/com/example/android/support/vectordrawable/app/AnimatedButtonBackground.java
+++ b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleAnimatedVectorDrawable.java
@@ -16,7 +16,6 @@
 
 package com.example.android.support.vectordrawable.app;
 
-import android.animation.ObjectAnimator;
 import android.app.Activity;
 import android.content.res.Resources;
 import android.os.Bundle;
@@ -26,24 +25,26 @@
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
+
 import com.example.android.support.vectordrawable.R;
 
 import java.text.DecimalFormat;
 
-public class AnimatedButtonBackground extends Activity implements View.OnClickListener{
+/**
+ * Simple demo for AnimatedVectorDrawableCompat.
+ */
+public class SimpleAnimatedVectorDrawable extends Activity implements View.OnClickListener {
     private static final String LOG_TAG = "TestActivity";
 
     private static final String LOGCAT = "VectorDrawable1";
-    protected int[] icon = {
-        R.drawable.animation_vector_drawable_grouping_1,
-        R.drawable.animation_vector_progress_bar,
-        R.drawable.btn_radio_on_to_off_bundle,
+    protected int[] mIcons = {
+            R.drawable.animation_vector_drawable_grouping_1,
+            R.drawable.animation_vector_progress_bar,
+            R.drawable.btn_radio_on_to_off_bundle,
     };
 
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        ObjectAnimator oa = new ObjectAnimator();
         super.onCreate(savedInstanceState);
         ScrollView scrollView = new ScrollView(this);
         LinearLayout container = new LinearLayout(this);
@@ -51,15 +52,15 @@
         container.setOrientation(LinearLayout.VERTICAL);
         Resources res = this.getResources();
         container.setBackgroundColor(0xFF888888);
-        AnimatedVectorDrawableCompat []d = new AnimatedVectorDrawableCompat[icon.length];
-        long time =  android.os.SystemClock.currentThreadTimeMillis();
-        for (int i = 0; i < icon.length; i++) {
-             d[i] = AnimatedVectorDrawableCompat.create(this, icon[i]);
+        AnimatedVectorDrawableCompat[] d = new AnimatedVectorDrawableCompat[mIcons.length];
+        long time = android.os.SystemClock.currentThreadTimeMillis();
+        for (int i = 0; i < mIcons.length; i++) {
+            d[i] = AnimatedVectorDrawableCompat.create(this, mIcons[i]);
         }
-        time =  android.os.SystemClock.currentThreadTimeMillis()-time;
+        time = android.os.SystemClock.currentThreadTimeMillis() - time;
         TextView t = new TextView(this);
         DecimalFormat df = new DecimalFormat("#.##");
-        t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+        t.setText("avgL=" + df.format(time / (mIcons.length)) + " ms");
         container.addView(t);
 
         addDrawableButtons(container, d);
diff --git a/samples/SupportVectorDrawable/static/src/com/example/android/support/vectordrawable/app/SimpleButtonBackground.java b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleStaticVectorDrawable.java
similarity index 86%
rename from samples/SupportVectorDrawable/static/src/com/example/android/support/vectordrawable/app/SimpleButtonBackground.java
rename to samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleStaticVectorDrawable.java
index 79a51ac..deee6c6 100644
--- a/samples/SupportVectorDrawable/static/src/com/example/android/support/vectordrawable/app/SimpleButtonBackground.java
+++ b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SimpleStaticVectorDrawable.java
@@ -26,15 +26,18 @@
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
+
 import com.example.android.support.vectordrawable.R;
 
 import java.text.DecimalFormat;
 
-public class SimpleButtonBackground extends Activity {
-    private static final String LOG_TAG = "SimpleButtonBackground";
+/**
+ * Simple demo for VectorDrawableCompat.
+ */
+public class SimpleStaticVectorDrawable extends Activity {
+    private static final String LOG_TAG = "SimpleStaticVectorDrawable";
 
-    private static final String LOGCAT = "VectorDrawable1";
-    protected int[] icon = {
+    protected int[] mIcons = {
             R.drawable.vector_drawable_scale0,
             R.drawable.vector_drawable_scale1,
             R.drawable.vector_drawable_scale2,
@@ -84,12 +87,12 @@
         container.setOrientation(LinearLayout.VERTICAL);
         Resources res = this.getResources();
         container.setBackgroundColor(0xFF888888);
-        VectorDrawableCompat []d = new VectorDrawableCompat[icon.length];
-        long time =  android.os.SystemClock.currentThreadTimeMillis();
-        for (int i = 0; i < icon.length; i++) {
-             d[i] = VectorDrawableCompat.create(res, icon[i], getTheme());
+        VectorDrawableCompat[] d = new VectorDrawableCompat[mIcons.length];
+        long time = android.os.SystemClock.currentThreadTimeMillis();
+        for (int i = 0; i < mIcons.length; i++) {
+            d[i] = VectorDrawableCompat.create(res, mIcons[i], getTheme());
         }
-        time =  android.os.SystemClock.currentThreadTimeMillis()-time;
+        time = android.os.SystemClock.currentThreadTimeMillis() - time;
 
         // Testing Tint on one particular case.
         if (d.length > 3) {
@@ -99,7 +102,7 @@
 
         // Testing Constant State like operation by creating the first 2 icons
         // from the 3rd one's constant state.
-        VectorDrawableCompat []extras = new VectorDrawableCompat[EXTRA_TESTS];
+        VectorDrawableCompat[] extras = new VectorDrawableCompat[EXTRA_TESTS];
         ConstantState state = d[0].getConstantState();
         extras[0] = (VectorDrawableCompat) state.newDrawable();
         extras[1] = (VectorDrawableCompat) state.newDrawable();
@@ -113,7 +116,7 @@
         // Just show the average create time as the first view.
         TextView t = new TextView(this);
         DecimalFormat df = new DecimalFormat("#.##");
-        t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+        t.setText("avgL=" + df.format(time / (mIcons.length)) + " ms");
         container.addView(t);
 
         addDrawableButtons(container, extras);
diff --git a/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SupportVectorDrawableDemos.java b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SupportVectorDrawableDemos.java
new file mode 100644
index 0000000..1bb3377
--- /dev/null
+++ b/samples/SupportVectorDrawableDemos/src/com/example/android/support/vectordrawable/app/SupportVectorDrawableDemos.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 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 com.example.android.support.vectordrawable.app;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The root level activity for this demo. Showing a list of sub demos.
+ */
+public class SupportVectorDrawableDemos extends ListActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        String path = intent.getStringExtra("com.example.android.apis.Path");
+
+        if (path == null) {
+            path = "";
+        }
+
+        setListAdapter(new SimpleAdapter(this, getData(path),
+                android.R.layout.simple_list_item_1, new String[]{"title"},
+                new int[]{android.R.id.text1}));
+        getListView().setTextFilterEnabled(true);
+    }
+
+    protected List<Map<String, Object>> getData(String prefix) {
+        List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>();
+
+        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory("android.intent.category.SAMPLE_CODE");
+
+        PackageManager pm = getPackageManager();
+        List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+        if (null == list) {
+            return myData;
+        }
+
+        String[] prefixPath;
+        String prefixWithSlash = prefix;
+
+        if (prefix.equals("")) {
+            prefixPath = null;
+        } else {
+            prefixPath = prefix.split("/");
+            prefixWithSlash = prefix + "/";
+        }
+
+        int len = list.size();
+
+        Map<String, Boolean> entries = new HashMap<String, Boolean>();
+
+        for (int i = 0; i < len; i++) {
+            ResolveInfo info = list.get(i);
+            CharSequence labelSeq = info.loadLabel(pm);
+            String label = labelSeq != null
+                    ? labelSeq.toString()
+                    : info.activityInfo.name;
+
+            if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+                String[] labelPath = label.split("/");
+
+                String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+                if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+                    addItem(myData, nextLabel, activityIntent(
+                            info.activityInfo.applicationInfo.packageName,
+                            info.activityInfo.name));
+                } else {
+                    if (entries.get(nextLabel) == null) {
+                        addItem(myData, nextLabel, browseIntent(
+                                prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
+                        entries.put(nextLabel, true);
+                    }
+                }
+            }
+        }
+
+        Collections.sort(myData, sDisplayNameComparator);
+
+        return myData;
+    }
+
+    private static final Comparator<Map<String, Object>> sDisplayNameComparator =
+            new Comparator<Map<String, Object>>() {
+                private final Collator mCollator = Collator.getInstance();
+
+                @Override
+                public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+                    return mCollator.compare(map1.get("title"), map2.get("title"));
+                }
+            };
+
+    protected Intent activityIntent(String pkg, String componentName) {
+        Intent result = new Intent();
+        result.setClassName(pkg, componentName);
+        return result;
+    }
+
+    protected Intent browseIntent(String path) {
+        Intent result = new Intent();
+        result.setClass(this, SupportVectorDrawableDemos.class);
+        result.putExtra("com.example.android.apis.Path", path);
+        return result;
+    }
+
+    protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+        Map<String, Object> temp = new HashMap<String, Object>();
+        temp.put("title", name);
+        temp.put("intent", intent);
+        data.add(temp);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        Map<String, Object> map = (Map<String, Object>) l.getItemAtPosition(position);
+
+        Intent intent = (Intent) map.get("intent");
+        startActivity(intent);
+    }
+}
diff --git a/settings.gradle b/settings.gradle
index 41d466e..1597c2e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -132,6 +132,9 @@
 include ':support-v13-demos'
 project(':support-v13-demos').projectDir = new File(samplesRoot, 'Support13Demos')
 
+include ':support-vector-drawable-demos'
+project(':support-vector-drawable-demos').projectDir = new File(samplesRoot, 'SupportVectorDrawableDemos')
+
 /////////////////////////////
 //
 // External
diff --git a/transition/Android.mk b/transition/Android.mk
index b647dfc..4e6f373 100644
--- a/transition/Android.mk
+++ b/transition/Android.mk
@@ -30,6 +30,8 @@
     $(call all-java-files-under,base) \
     $(call all-java-files-under,api14) \
     $(call all-java-files-under,api18) \
+    $(call all-java-files-under,api19) \
+    $(call all-java-files-under,api21) \
     $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_SHARED_ANDROID_LIBRARIES := \
@@ -37,5 +39,5 @@
     android-support-v4
 LOCAL_JAR_EXCLUDE_FILES := none
 LOCAL_JAVA_LANGUAGE_VERSION := 1.7
-LOCAL_AAPT_FLAGS := --add-javadoc-annotation doconly
+LOCAL_AAPT_FLAGS := --no-version-transitions --add-javadoc-annotation doconly
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/transition/api14/android/support/transition/AnimatorUtilsApi14.java b/transition/api14/android/support/transition/AnimatorUtilsApi14.java
new file mode 100644
index 0000000..c3d47cc
--- /dev/null
+++ b/transition/api14/android/support/transition/AnimatorUtilsApi14.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+
+@RequiresApi(14)
+class AnimatorUtilsApi14 implements AnimatorUtilsImpl {
+
+    @Override
+    public void addPauseListener(@NonNull Animator animator,
+            @NonNull AnimatorListenerAdapter listener) {
+        // Do nothing
+    }
+
+}
diff --git a/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
new file mode 100644
index 0000000..6fb444d
--- /dev/null
+++ b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.ObjectAnimator;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.support.annotation.RequiresApi;
+import android.util.Property;
+
+@RequiresApi(14)
+class ObjectAnimatorUtilsApi14 implements ObjectAnimatorUtilsImpl {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> ObjectAnimator ofInt(T target, String xPropertyName, String yPropertyName,
+            Path path) {
+        Class<?> hostType = target.getClass();
+        Property<T, Integer> px = (Property<T, Integer>) Property.of(hostType, Integer.class,
+                xPropertyName);
+        Property<T, Integer> py = (Property<T, Integer>) Property.of(hostType, Integer.class,
+                yPropertyName);
+        return ObjectAnimator.ofFloat(target,
+                new PathProperty<>(
+                        new CastIntegerProperty<>(px),
+                        new CastIntegerProperty<>(py),
+                        path),
+                0f, 1f);
+    }
+
+    @Override
+    public <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
+            Property<T, Integer> yProperty, Path path) {
+        return ObjectAnimator.ofFloat(target,
+                new PathProperty<>(
+                        new CastIntegerProperty<>(xProperty),
+                        new CastIntegerProperty<>(yProperty),
+                        path),
+                0f, 1f);
+    }
+
+    @Override
+    public <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
+            Property<T, Float> yProperty, Path path) {
+        return ObjectAnimator.ofFloat(target,
+                new PathProperty<>(xProperty, yProperty, path));
+    }
+
+    /**
+     * Converts a {@link Property} with Integer value type to a {@link Property} with a Float
+     * value type.
+     *
+     * @param <T> The target type
+     */
+    private static class CastIntegerProperty<T> extends Property<T, Float> {
+
+        private final Property<T, Integer> mProperty;
+
+        CastIntegerProperty(Property<T, Integer> property) {
+            super(Float.class, property.getName());
+            mProperty = property;
+        }
+
+        @Override
+        public Float get(T object) {
+            return (float) mProperty.get(object);
+        }
+
+        @Override
+        public void set(T object, Float value) {
+            mProperty.set(object,
+                    // This cannot be a simple cast to make animations pixel perfect.
+                    Math.round(value));
+        }
+
+    }
+
+    /**
+     * A special {@link Property} that can animate a pair of properties bi-dimensionally along the
+     * specified path.
+     * <p>
+     * This property should always be used with Animator that sets float fractions between
+     * {@code 0.f} and {@code 1.f}. For example, setting {@code 0.5f} to this property sets the
+     * values right in the middle of the specified path to the underlying properties.
+     * <p>
+     * Unlike many of the platform built-in properties, instances of this class cannot be reused
+     * for later animations.
+     */
+    private static class PathProperty<T> extends Property<T, Float> {
+
+        private final PathMeasure mPathMeasure;
+        private final float mPathLength;
+        private final float[] mPosition = new float[2];
+        private final Property<T, Float> mXProperty;
+        private final Property<T, Float> mYProperty;
+        private float mCurrentFraction;
+
+        PathProperty(Property<T, Float> xProperty, Property<T, Float> yProperty, Path path) {
+            super(Float.class, xProperty.getName() + "/" + yProperty.getName());
+            mXProperty = xProperty;
+            mYProperty = yProperty;
+            mPathMeasure = new PathMeasure(path, false);
+            mPathLength = mPathMeasure.getLength();
+        }
+
+        @Override
+        public Float get(T t) {
+            return mCurrentFraction;
+        }
+
+        @Override
+        public void set(T view, Float fraction) {
+            mCurrentFraction = fraction;
+            mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
+            mXProperty.set(view, mPosition[0]);
+            mYProperty.set(view, mPosition[1]);
+        }
+
+    }
+
+}
diff --git a/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
new file mode 100644
index 0000000..7bcd36e
--- /dev/null
+++ b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.PropertyValuesHolder;
+import android.animation.TypeEvaluator;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PointF;
+import android.support.annotation.RequiresApi;
+import android.util.Property;
+
+@RequiresApi(14)
+class PropertyValuesHolderUtilsApi14 implements PropertyValuesHolderUtilsImpl {
+
+    @Override
+    public PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path) {
+        return PropertyValuesHolder.ofObject(property, new PathEvaluator(path));
+    }
+
+    private static class PathEvaluator implements TypeEvaluator<PointF> {
+
+        private final PointF mPointF = new PointF();
+        private final PathMeasure mPathMeasure;
+        private final float mPathLength;
+        private final float[] mPosition = new float[2];
+
+        PathEvaluator(Path path) {
+            mPathMeasure = new PathMeasure(path, false);
+            mPathLength = mPathMeasure.getLength();
+        }
+
+        @Override
+        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
+            mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
+            mPointF.set(mPosition[0], mPosition[1]);
+            return mPointF;
+        }
+
+    }
+
+}
diff --git a/transition/api14/android/support/transition/ViewUtilsApi14.java b/transition/api14/android/support/transition/ViewUtilsApi14.java
index 6131114..a8ea8db 100644
--- a/transition/api14/android/support/transition/ViewUtilsApi14.java
+++ b/transition/api14/android/support/transition/ViewUtilsApi14.java
@@ -33,4 +33,14 @@
         return new WindowIdApi14(view.getWindowToken());
     }
 
+    @Override
+    public void setTransitionAlpha(@NonNull View view, float alpha) {
+        view.setAlpha(alpha);
+    }
+
+    @Override
+    public float getTransitionAlpha(@NonNull View view) {
+        return view.getAlpha();
+    }
+
 }
diff --git a/transition/api19/android/support/transition/AnimatorUtilsApi19.java b/transition/api19/android/support/transition/AnimatorUtilsApi19.java
new file mode 100644
index 0000000..38e3942
--- /dev/null
+++ b/transition/api19/android/support/transition/AnimatorUtilsApi19.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+
+@RequiresApi(19)
+class AnimatorUtilsApi19 extends AnimatorUtilsApi14 {
+
+    @Override
+    public void addPauseListener(@NonNull Animator animator,
+            @NonNull AnimatorListenerAdapter listener) {
+        animator.addPauseListener(listener);
+    }
+
+}
diff --git a/transition/api19/android/support/transition/ViewUtilsApi19.java b/transition/api19/android/support/transition/ViewUtilsApi19.java
new file mode 100644
index 0000000..2773a41
--- /dev/null
+++ b/transition/api19/android/support/transition/ViewUtilsApi19.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.util.Log;
+import android.view.View;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+@RequiresApi(19)
+class ViewUtilsApi19 extends ViewUtilsApi18 {
+
+    private static final String TAG = "ViewUtilsApi19";
+
+    private static Method sSetTransitionAlphaMethod;
+    private static boolean sSetTransitionAlphaMethodFetched;
+    private static Method sGetTransitionAlphaMethod;
+    private static boolean sGetTransitionAlphaMethodFetched;
+
+    @Override
+    public void setTransitionAlpha(@NonNull View view, float alpha) {
+        fetchSetTransitionAlphaMethod();
+        if (sSetTransitionAlphaMethod != null) {
+            try {
+                sSetTransitionAlphaMethod.invoke(view, alpha);
+            } catch (IllegalAccessException e) {
+                // Do nothing
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e.getCause());
+            }
+        } else {
+            view.setAlpha(alpha);
+        }
+    }
+
+    @Override
+    public float getTransitionAlpha(@NonNull View view) {
+        fetchGetTransitionAlphaMethod();
+        if (sGetTransitionAlphaMethod != null) {
+            try {
+                return (Float) sGetTransitionAlphaMethod.invoke(view);
+            } catch (IllegalAccessException e) {
+                // Do nothing
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e.getCause());
+            }
+        }
+        return super.getTransitionAlpha(view);
+    }
+
+    private void fetchSetTransitionAlphaMethod() {
+        if (!sSetTransitionAlphaMethodFetched) {
+            try {
+                sSetTransitionAlphaMethod = View.class.getDeclaredMethod("setTransitionAlpha",
+                        float.class);
+                sSetTransitionAlphaMethod.setAccessible(true);
+            } catch (NoSuchMethodException e) {
+                Log.i(TAG, "Failed to retrieve setTransitionAlpha method", e);
+            }
+            sSetTransitionAlphaMethodFetched = true;
+        }
+    }
+
+    private void fetchGetTransitionAlphaMethod() {
+        if (!sGetTransitionAlphaMethodFetched) {
+            try {
+                sGetTransitionAlphaMethod = View.class.getDeclaredMethod("getTransitionAlpha");
+                sGetTransitionAlphaMethod.setAccessible(true);
+            } catch (NoSuchMethodException e) {
+                Log.i(TAG, "Failed to retrieve getTransitionAlpha method", e);
+            }
+            sGetTransitionAlphaMethodFetched = true;
+        }
+    }
+
+}
diff --git a/transition/api21/android/support/transition/ObjectAnimatorUtilsApi21.java b/transition/api21/android/support/transition/ObjectAnimatorUtilsApi21.java
new file mode 100644
index 0000000..6e23fa3
--- /dev/null
+++ b/transition/api21/android/support/transition/ObjectAnimatorUtilsApi21.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.ObjectAnimator;
+import android.graphics.Path;
+import android.support.annotation.RequiresApi;
+import android.util.Property;
+
+@RequiresApi(21)
+class ObjectAnimatorUtilsApi21 implements ObjectAnimatorUtilsImpl {
+
+    @Override
+    public <T> ObjectAnimator ofInt(T target, String xPropertyName, String yPropertyName,
+            Path path) {
+        return ObjectAnimator.ofInt(target, xPropertyName, yPropertyName, path);
+    }
+
+    @Override
+    public <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
+            Property<T, Integer> yProperty, Path path) {
+        return ObjectAnimator.ofInt(target, xProperty, yProperty, path);
+    }
+
+    @Override
+    public <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
+            Property<T, Float> yProperty, Path path) {
+        return ObjectAnimator.ofFloat(target, xProperty, yProperty, path);
+    }
+
+}
diff --git a/transition/api21/android/support/transition/PropertyValuesHolderUtilsApi21.java b/transition/api21/android/support/transition/PropertyValuesHolderUtilsApi21.java
new file mode 100644
index 0000000..5f6d117
--- /dev/null
+++ b/transition/api21/android/support/transition/PropertyValuesHolderUtilsApi21.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.PropertyValuesHolder;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.support.annotation.RequiresApi;
+import android.util.Property;
+
+@RequiresApi(21)
+class PropertyValuesHolderUtilsApi21 implements PropertyValuesHolderUtilsImpl {
+
+    @Override
+    public PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path) {
+        return PropertyValuesHolder.ofObject(property, null, path);
+    }
+
+}
diff --git a/transition/base/android/support/transition/AnimatorUtilsImpl.java b/transition/base/android/support/transition/AnimatorUtilsImpl.java
new file mode 100644
index 0000000..ce1c9cc
--- /dev/null
+++ b/transition/base/android/support/transition/AnimatorUtilsImpl.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.support.annotation.NonNull;
+
+interface AnimatorUtilsImpl {
+
+    void addPauseListener(@NonNull Animator animator, @NonNull AnimatorListenerAdapter listener);
+
+}
diff --git a/transition/base/android/support/transition/ObjectAnimatorUtilsImpl.java b/transition/base/android/support/transition/ObjectAnimatorUtilsImpl.java
new file mode 100644
index 0000000..222da9f
--- /dev/null
+++ b/transition/base/android/support/transition/ObjectAnimatorUtilsImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.ObjectAnimator;
+import android.graphics.Path;
+import android.util.Property;
+
+interface ObjectAnimatorUtilsImpl {
+
+    <T> ObjectAnimator ofInt(T target, String xPropertyName, String yPropertyName, Path path);
+
+    <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
+            Property<T, Integer> yProperty, Path path);
+
+    <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
+            Property<T, Float> yProperty, Path path);
+
+}
diff --git a/transition/base/android/support/transition/PropertyValuesHolderUtilsImpl.java b/transition/base/android/support/transition/PropertyValuesHolderUtilsImpl.java
new file mode 100644
index 0000000..8ec31eb
--- /dev/null
+++ b/transition/base/android/support/transition/PropertyValuesHolderUtilsImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.PropertyValuesHolder;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.util.Property;
+
+interface PropertyValuesHolderUtilsImpl {
+
+    PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path);
+
+}
diff --git a/transition/base/android/support/transition/ViewUtilsImpl.java b/transition/base/android/support/transition/ViewUtilsImpl.java
index 188752d..68bf350 100644
--- a/transition/base/android/support/transition/ViewUtilsImpl.java
+++ b/transition/base/android/support/transition/ViewUtilsImpl.java
@@ -27,4 +27,8 @@
 
     WindowIdImpl getWindowId(@NonNull View view);
 
+    void setTransitionAlpha(@NonNull View view, float alpha);
+
+    float getTransitionAlpha(@NonNull View view);
+
 }
diff --git a/transition/build.gradle b/transition/build.gradle
index 036c010..57d1837 100644
--- a/transition/build.gradle
+++ b/transition/build.gradle
@@ -27,6 +27,8 @@
                 'base',
                 'api14',
                 'api18',
+                'api19',
+                'api21',
                 'src'
         ]
         main.res.srcDirs = [
@@ -34,6 +36,10 @@
                 'res-public'
         ]
     }
+
+    aaptOptions {
+        additionalParameters "--no-version-transitions"
+    }
 }
 
 supportLibrary {
diff --git a/transition/src/android/support/transition/AnimatorUtils.java b/transition/src/android/support/transition/AnimatorUtils.java
new file mode 100644
index 0000000..4bd7625
--- /dev/null
+++ b/transition/src/android/support/transition/AnimatorUtils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.os.Build;
+import android.support.annotation.NonNull;
+
+class AnimatorUtils {
+
+    private static final AnimatorUtilsImpl IMPL;
+
+    static {
+        if (Build.VERSION.SDK_INT >= 19) {
+            IMPL = new AnimatorUtilsApi19();
+        } else {
+            IMPL = new AnimatorUtilsApi14();
+        }
+    }
+
+    static void addPauseListener(@NonNull Animator animator,
+            @NonNull AnimatorListenerAdapter listener) {
+        IMPL.addPauseListener(animator, listener);
+    }
+
+}
diff --git a/transition/src/android/support/transition/ArcMotion.java b/transition/src/android/support/transition/ArcMotion.java
new file mode 100644
index 0000000..30cdd20
--- /dev/null
+++ b/transition/src/android/support/transition/ArcMotion.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.graphics.Path;
+
+/**
+ * A PathMotion that generates a curved path along an arc on an imaginary circle containing
+ * the two points. If the horizontal distance between the points is less than the vertical
+ * distance, then the circle's center point will be horizontally aligned with the end point. If the
+ * vertical distance is less than the horizontal distance then the circle's center point
+ * will be vertically aligned with the end point.
+ * <p>
+ * When the two points are near horizontal or vertical, the curve of the motion will be
+ * small as the center of the circle will be far from both points. To force curvature of
+ * the path, {@link #setMinimumHorizontalAngle(float)} and
+ * {@link #setMinimumVerticalAngle(float)} may be used to set the minimum angle of the
+ * arc between two points.
+ * </p>
+ */
+public class ArcMotion extends PathMotion {
+
+    private static final float DEFAULT_MAX_ANGLE_DEGREES = 70;
+    private static final float DEFAULT_MAX_TANGENT = (float)
+            Math.tan(Math.toRadians(DEFAULT_MAX_ANGLE_DEGREES / 2));
+
+    private float mMinimumHorizontalAngle = 0;
+    private float mMinimumVerticalAngle = 0;
+    private float mMaximumAngle = DEFAULT_MAX_ANGLE_DEGREES;
+    private float mMinimumHorizontalTangent = 0;
+    private float mMinimumVerticalTangent = 0;
+    private float mMaximumTangent = DEFAULT_MAX_TANGENT;
+
+    public ArcMotion() {
+    }
+
+    /**
+     * Sets the minimum arc along the circle between two points aligned near horizontally.
+     * When start and end points are close to horizontal, the calculated center point of the
+     * circle will be far from both points, giving a near straight path between the points.
+     * By setting a minimum angle, this forces the center point to be closer and give an
+     * exaggerated curve to the path.
+     * <p>The default value is 0.</p>
+     *
+     * @param angleInDegrees The minimum angle of the arc on a circle describing the Path
+     *                       between two nearly horizontally-separated points.
+     */
+    public void setMinimumHorizontalAngle(float angleInDegrees) {
+        mMinimumHorizontalAngle = angleInDegrees;
+        mMinimumHorizontalTangent = toTangent(angleInDegrees);
+    }
+
+    /**
+     * Returns the minimum arc along the circle between two points aligned near horizontally.
+     * When start and end points are close to horizontal, the calculated center point of the
+     * circle will be far from both points, giving a near straight path between the points.
+     * By setting a minimum angle, this forces the center point to be closer and give an
+     * exaggerated curve to the path.
+     * <p>The default value is 0.</p>
+     *
+     * @return The minimum arc along the circle between two points aligned near horizontally.
+     */
+    public float getMinimumHorizontalAngle() {
+        return mMinimumHorizontalAngle;
+    }
+
+    /**
+     * Sets the minimum arc along the circle between two points aligned near vertically.
+     * When start and end points are close to vertical, the calculated center point of the
+     * circle will be far from both points, giving a near straight path between the points.
+     * By setting a minimum angle, this forces the center point to be closer and give an
+     * exaggerated curve to the path.
+     * <p>The default value is 0.</p>
+     *
+     * @param angleInDegrees The minimum angle of the arc on a circle describing the Path
+     *                       between two nearly vertically-separated points.
+     */
+    public void setMinimumVerticalAngle(float angleInDegrees) {
+        mMinimumVerticalAngle = angleInDegrees;
+        mMinimumVerticalTangent = toTangent(angleInDegrees);
+    }
+
+    /**
+     * Returns the minimum arc along the circle between two points aligned near vertically.
+     * When start and end points are close to vertical, the calculated center point of the
+     * circle will be far from both points, giving a near straight path between the points.
+     * By setting a minimum angle, this forces the center point to be closer and give an
+     * exaggerated curve to the path.
+     * <p>The default value is 0.</p>
+     *
+     * @return The minimum angle of the arc on a circle describing the Path
+     * between two nearly vertically-separated points.
+     */
+    public float getMinimumVerticalAngle() {
+        return mMinimumVerticalAngle;
+    }
+
+    /**
+     * Sets the maximum arc along the circle between two points. When start and end points
+     * have close to equal x and y differences, the curve between them is large. This forces
+     * the curved path to have an arc of at most the given angle.
+     * <p>The default value is 70 degrees.</p>
+     *
+     * @param angleInDegrees The maximum angle of the arc on a circle describing the Path
+     *                       between the start and end points.
+     */
+    public void setMaximumAngle(float angleInDegrees) {
+        mMaximumAngle = angleInDegrees;
+        mMaximumTangent = toTangent(angleInDegrees);
+    }
+
+    /**
+     * Returns the maximum arc along the circle between two points. When start and end points
+     * have close to equal x and y differences, the curve between them is large. This forces
+     * the curved path to have an arc of at most the given angle.
+     * <p>The default value is 70 degrees.</p>
+     *
+     * @return The maximum angle of the arc on a circle describing the Path
+     * between the start and end points.
+     */
+    public float getMaximumAngle() {
+        return mMaximumAngle;
+    }
+
+    private static float toTangent(float arcInDegrees) {
+        if (arcInDegrees < 0 || arcInDegrees > 90) {
+            throw new IllegalArgumentException("Arc must be between 0 and 90 degrees");
+        }
+        return (float) Math.tan(Math.toRadians(arcInDegrees / 2));
+    }
+
+    @Override
+    public Path getPath(float startX, float startY, float endX, float endY) {
+        // Here's a little ascii art to show how this is calculated:
+        // c---------- b
+        //  \        / |
+        //    \     d  |
+        //      \  /   e
+        //        a----f
+        // This diagram assumes that the horizontal distance is less than the vertical
+        // distance between The start point (a) and end point (b).
+        // d is the midpoint between a and b. c is the center point of the circle with
+        // This path is formed by assuming that start and end points are in
+        // an arc on a circle. The end point is centered in the circle vertically
+        // and start is a point on the circle.
+
+        // Triangles bfa and bde form similar right triangles. The control points
+        // for the cubic Bezier arc path are the midpoints between a and e and e and b.
+
+        Path path = new Path();
+        path.moveTo(startX, startY);
+
+        float ex;
+        float ey;
+        float deltaX = endX - startX;
+        float deltaY = endY - startY;
+
+        // hypotenuse squared.
+        float h2 = deltaX * deltaX + deltaY * deltaY;
+
+        // Midpoint between start and end
+        float dx = (startX + endX) / 2;
+        float dy = (startY + endY) / 2;
+
+        // Distance squared between end point and mid point is (1/2 hypotenuse)^2
+        float midDist2 = h2 * 0.25f;
+
+        float minimumArcDist2;
+
+        boolean isMovingUpwards = startY > endY;
+
+        if ((Math.abs(deltaX) < Math.abs(deltaY))) {
+            // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
+            // Therefore, eb = ab * bd / fb
+            // ab = hypotenuse
+            // bd = hypotenuse/2
+            // fb = deltaY
+            float eDistY = Math.abs(h2 / (2 * deltaY));
+            if (isMovingUpwards) {
+                ey = endY + eDistY;
+                ex = endX;
+            } else {
+                ey = startY + eDistY;
+                ex = startX;
+            }
+
+            minimumArcDist2 = midDist2 * mMinimumVerticalTangent
+                    * mMinimumVerticalTangent;
+        } else {
+            // Same as above, but flip X & Y and account for negative eDist
+            float eDistX = h2 / (2 * deltaX);
+            if (isMovingUpwards) {
+                ex = startX + eDistX;
+                ey = startY;
+            } else {
+                ex = endX - eDistX;
+                ey = endY;
+            }
+
+            minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
+                    * mMinimumHorizontalTangent;
+        }
+        float arcDistX = dx - ex;
+        float arcDistY = dy - ey;
+        float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY;
+
+        float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
+
+        float newArcDistance2 = 0;
+        if (arcDist2 < minimumArcDist2) {
+            newArcDistance2 = minimumArcDist2;
+        } else if (arcDist2 > maximumArcDist2) {
+            newArcDistance2 = maximumArcDist2;
+        }
+        if (newArcDistance2 != 0) {
+            float ratio2 = newArcDistance2 / arcDist2;
+            float ratio = (float) Math.sqrt(ratio2);
+            ex = dx + (ratio * (ex - dx));
+            ey = dy + (ratio * (ey - dy));
+        }
+        float control1X = (startX + ex) / 2;
+        float control1Y = (startY + ey) / 2;
+        float control2X = (ex + endX) / 2;
+        float control2Y = (ey + endY) / 2;
+        path.cubicTo(control1X, control1Y, control2X, control2Y, endX, endY);
+        return path;
+    }
+
+}
diff --git a/transition/src/android/support/transition/AutoTransition.java b/transition/src/android/support/transition/AutoTransition.java
index ec0d404..02b49e2 100644
--- a/transition/src/android/support/transition/AutoTransition.java
+++ b/transition/src/android/support/transition/AutoTransition.java
@@ -16,11 +16,16 @@
 
 package android.support.transition;
 
+import android.content.Context;
+import android.util.AttributeSet;
+
 /**
  * Utility class for creating a default transition that automatically fades,
  * moves, and resizes views during a scene change.
  *
- * <p>Unlike the platform version, this does not support use in XML resources.</p>
+ * <p>An AutoTransition can be described in a resource file by using the
+ * tag <code>autoTransition</code>, along with the other standard
+ * attributes of {@link Transition}.</p>
  */
 public class AutoTransition extends TransitionSet {
 
@@ -30,6 +35,15 @@
      * targets, and finally fades in appearing targets.
      */
     public AutoTransition() {
+        init();
+    }
+
+    public AutoTransition(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init() {
         setOrdering(ORDERING_SEQUENTIAL);
         addTransition(new Fade(Fade.OUT)).
                 addTransition(new ChangeBounds()).
diff --git a/transition/src/android/support/transition/ChangeBounds.java b/transition/src/android/support/transition/ChangeBounds.java
index ae119a4..4d84098 100644
--- a/transition/src/android/support/transition/ChangeBounds.java
+++ b/transition/src/android/support/transition/ChangeBounds.java
@@ -20,12 +20,19 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
+import android.util.Property;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -35,7 +42,8 @@
  * This transition captures the layout bounds of target views before and after
  * the scene change and animates those changes during the transition.
  *
- * <p>Unlike the platform version, this does not support use in XML resources.</p>
+ * <p>A ChangeBounds transition can be described in a resource file by using the
+ * tag <code>changeBounds</code>, along with the other standard attributes of Transition.</p>
  */
 public class ChangeBounds extends Transition {
 
@@ -50,12 +58,37 @@
             PROPNAME_WINDOW_Y
     };
 
-    int[] mTempLocation = new int[2];
-    boolean mResizeClip = false;
-    boolean mReparent = false;
+    private static final Property<Drawable, PointF> DRAWABLE_ORIGIN_PROPERTY =
+            new Property<Drawable, PointF>(PointF.class, "boundsOrigin") {
+                private Rect mBounds = new Rect();
+
+                @Override
+                public void set(Drawable object, PointF value) {
+                    object.copyBounds(mBounds);
+                    mBounds.offsetTo(Math.round(value.x), Math.round(value.y));
+                    object.setBounds(mBounds);
+                }
+
+                @Override
+                public PointF get(Drawable object) {
+                    object.copyBounds(mBounds);
+                    return new PointF(mBounds.left, mBounds.top);
+                }
+            };
+
+    private int[] mTempLocation = new int[2];
+    private boolean mResizeClip = false;
+    private boolean mReparent = false;
 
     private static RectEvaluator sRectEvaluator = new RectEvaluator();
 
+    public ChangeBounds() {
+    }
+
+    public ChangeBounds(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
     @Nullable
     @Override
     public String[] getTransitionProperties() {
@@ -81,12 +114,17 @@
 
     private void captureValues(TransitionValues values) {
         View view = values.view;
-        values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
-                view.getRight(), view.getBottom()));
-        values.values.put(PROPNAME_PARENT, values.view.getParent());
-        values.view.getLocationInWindow(mTempLocation);
-        values.values.put(PROPNAME_WINDOW_X, mTempLocation[0]);
-        values.values.put(PROPNAME_WINDOW_Y, mTempLocation[1]);
+
+        if (ViewCompat.isLaidOut(view) || view.getWidth() != 0 || view.getHeight() != 0) {
+            values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
+                    view.getRight(), view.getBottom()));
+            values.values.put(PROPNAME_PARENT, values.view.getParent());
+            if (mReparent) {
+                values.view.getLocationInWindow(mTempLocation);
+                values.values.put(PROPNAME_WINDOW_X, mTempLocation[0]);
+                values.values.put(PROPNAME_WINDOW_Y, mTempLocation[1]);
+            }
+        }
     }
 
     @Override
@@ -99,6 +137,19 @@
         captureValues(transitionValues);
     }
 
+    private boolean parentMatches(View startParent, View endParent) {
+        boolean parentMatches = true;
+        if (mReparent) {
+            TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+            if (endValues == null) {
+                parentMatches = startParent == endParent;
+            } else {
+                parentMatches = endParent == endValues.view;
+            }
+        }
+        return parentMatches;
+    }
+
     @Override
     @Nullable
     public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
@@ -114,13 +165,7 @@
             return null;
         }
         final View view = endValues.view;
-        boolean parentsEqual = (startParent == endParent)
-                || (startParent.getId() == endParent.getId());
-        // TODO: Might want reparenting to be separate/subclass transition, or at least
-        // triggered by a property on ChangeBounds. Otherwise, we're forcing the requirement that
-        // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
-        // of reparenting the views.
-        if (!mReparent || parentsEqual) {
+        if (parentMatches(startParent, endParent)) {
             Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
             Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
             int startLeft = startBounds.left;
@@ -152,35 +197,36 @@
             }
             if (numChanges > 0) {
                 if (!mResizeClip) {
-                    PropertyValuesHolder[] pvh = new PropertyValuesHolder[numChanges];
-                    int pvhIndex = 0;
-                    if (startLeft != endLeft) {
-                        view.setLeft(startLeft);
+                    Animator anim;
+                    if (startWidth == endWidth && startHeight == endHeight) {
+                        view.offsetLeftAndRight(startLeft - view.getLeft());
+                        view.offsetTopAndBottom(startTop - view.getTop());
+                        Path positionPath = getPathMotion().getPath(0, 0, endLeft - startLeft,
+                                endTop - startTop);
+                        anim = ObjectAnimatorUtils.ofInt(view, new HorizontalOffsetProperty(),
+                                new VerticalOffsetProperty(), positionPath);
+                    } else {
+                        if (startLeft != endLeft) view.setLeft(startLeft);
+                        if (startTop != endTop) view.setTop(startTop);
+                        if (startRight != endRight) view.setRight(startRight);
+                        if (startBottom != endBottom) view.setBottom(startBottom);
+                        ObjectAnimator topLeftAnimator = null;
+                        if (startLeft != endLeft || startTop != endTop) {
+                            Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
+                                    endLeft, endTop);
+                            topLeftAnimator = ObjectAnimatorUtils
+                                    .ofInt(view, "left", "top", topLeftPath);
+                        }
+                        ObjectAnimator bottomRightAnimator = null;
+                        if (startRight != endRight || startBottom != endBottom) {
+                            Path bottomRightPath = getPathMotion().getPath(startRight, startBottom,
+                                    endRight, endBottom);
+                            bottomRightAnimator = ObjectAnimatorUtils.ofInt(view, "right", "bottom",
+                                    bottomRightPath);
+                        }
+                        anim = TransitionUtils.mergeAnimators(topLeftAnimator,
+                                bottomRightAnimator);
                     }
-                    if (startTop != endTop) {
-                        view.setTop(startTop);
-                    }
-                    if (startRight != endRight) {
-                        view.setRight(startRight);
-                    }
-                    if (startBottom != endBottom) {
-                        view.setBottom(startBottom);
-                    }
-                    if (startLeft != endLeft) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofInt("left", startLeft, endLeft);
-                    }
-                    if (startTop != endTop) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofInt("top", startTop, endTop);
-                    }
-                    if (startRight != endRight) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofInt("right",
-                                startRight, endRight);
-                    }
-                    if (startBottom != endBottom) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofInt("bottom",
-                                startBottom, endBottom);
-                    }
-                    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, pvh);
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         ViewGroupUtils.suppressLayout(parent, true);
@@ -232,33 +278,21 @@
                     float transYDelta = endTop - startTop;
                     int widthDelta = endWidth - startWidth;
                     int heightDelta = endHeight - startHeight;
-                    numChanges = 0;
-                    if (transXDelta != 0) {
-                        numChanges++;
+                    ObjectAnimator translationAnimator = null;
+                    if (transXDelta != 0 || transYDelta != 0) {
+                        Path topLeftPath = getPathMotion().getPath(0, 0, transXDelta, transYDelta);
+                        translationAnimator = ObjectAnimatorUtils.ofFloat(view, View.TRANSLATION_X,
+                                View.TRANSLATION_Y, topLeftPath);
                     }
-                    if (transYDelta != 0) {
-                        numChanges++;
-                    }
-                    if (widthDelta != 0 || heightDelta != 0) {
-                        numChanges++;
-                    }
-                    PropertyValuesHolder[] pvh = new PropertyValuesHolder[numChanges];
-                    int pvhIndex = 0;
-                    if (transXDelta != 0) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofFloat("translationX",
-                                view.getTranslationX(), 0);
-                    }
-                    if (transYDelta != 0) {
-                        pvh[pvhIndex++] = PropertyValuesHolder.ofFloat("translationY",
-                                view.getTranslationY(), 0);
-                    }
+                    ObjectAnimator clipAnimator = null;
                     if (widthDelta != 0 || heightDelta != 0) {
                         Rect tempStartBounds = new Rect(0, 0, startWidth, startHeight);
                         Rect tempEndBounds = new Rect(0, 0, endWidth, endHeight);
-//                        pvh[pvhIndex++] = PropertyValuesHolder.ofObject("clipBounds",
-//                                sRectEvaluator, tempStartBounds, tempEndBounds);
+                        clipAnimator = ObjectAnimator.ofObject(view, ViewUtils.CLIP_BOUNDS,
+                                sRectEvaluator, tempStartBounds, tempEndBounds);
                     }
-                    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, pvh);
+                    Animator anim = TransitionUtils.mergeAnimators(translationAnimator,
+                            clipAnimator);
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         ViewGroupUtils.suppressLayout(parent, true);
@@ -293,7 +327,7 @@
                     anim.addListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationEnd(Animator animation) {
-//                            view.setClipBounds(null);
+                            ViewCompat.setClipBounds(view, null);
                         }
                     });
                     return anim;
@@ -311,22 +345,22 @@
                         Bitmap.Config.ARGB_8888);
                 Canvas canvas = new Canvas(bitmap);
                 view.draw(canvas);
+                @SuppressWarnings("deprecation")
                 final BitmapDrawable drawable = new BitmapDrawable(bitmap);
-                view.setVisibility(View.INVISIBLE);
+                final float transitionAlpha = ViewUtils.getTransitionAlpha(view);
+                ViewUtils.setTransitionAlpha(view, 0);
                 ViewUtils.getOverlay(sceneRoot).add(drawable);
-                Rect startBounds1 = new Rect(startX - mTempLocation[0], startY - mTempLocation[1],
-                        startX - mTempLocation[0] + view.getWidth(),
-                        startY - mTempLocation[1] + view.getHeight());
-                Rect endBounds1 = new Rect(endX - mTempLocation[0], endY - mTempLocation[1],
-                        endX - mTempLocation[0] + view.getWidth(),
-                        endY - mTempLocation[1] + view.getHeight());
-                ObjectAnimator anim = ObjectAnimator.ofObject(drawable, "bounds",
-                        sRectEvaluator, startBounds1, endBounds1);
+                Path topLeftPath = getPathMotion().getPath(startX - mTempLocation[0],
+                        startY - mTempLocation[1], endX - mTempLocation[0],
+                        endY - mTempLocation[1]);
+                PropertyValuesHolder origin = PropertyValuesHolderUtils.ofPointF(
+                        DRAWABLE_ORIGIN_PROPERTY, topLeftPath);
+                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, origin);
                 anim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         ViewUtils.getOverlay(sceneRoot).remove(drawable);
-                        view.setVisibility(View.VISIBLE);
+                        ViewUtils.setTransitionAlpha(view, transitionAlpha);
                     }
                 });
                 return anim;
@@ -335,4 +369,48 @@
         return null;
     }
 
+    private abstract static class OffsetProperty extends Property<View, Integer> {
+        int mPreviousValue;
+
+        OffsetProperty(String name) {
+            super(Integer.class, name);
+        }
+
+        @Override
+        public void set(View view, Integer value) {
+            int offset = value - mPreviousValue;
+            offsetBy(view, offset);
+            mPreviousValue = value;
+        }
+
+        @Override
+        public Integer get(View object) {
+            return null;
+        }
+
+        protected abstract void offsetBy(View view, int by);
+    }
+
+    private static class HorizontalOffsetProperty extends OffsetProperty {
+        HorizontalOffsetProperty() {
+            super("offsetLeftAndRight");
+        }
+
+        @Override
+        protected void offsetBy(View view, int by) {
+            ViewCompat.offsetLeftAndRight(view, by);
+        }
+    }
+
+    private static class VerticalOffsetProperty extends OffsetProperty {
+        VerticalOffsetProperty() {
+            super("offsetTopAndBottom");
+        }
+
+        @Override
+        protected void offsetBy(View view, int by) {
+            ViewCompat.offsetTopAndBottom(view, by);
+        }
+    }
+
 }
diff --git a/transition/src/android/support/transition/Fade.java b/transition/src/android/support/transition/Fade.java
index c2b5711..1b65c18 100644
--- a/transition/src/android/support/transition/Fade.java
+++ b/transition/src/android/support/transition/Fade.java
@@ -19,8 +19,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.support.annotation.NonNull;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.support.v4.content.res.TypedArrayUtils;
 import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -50,29 +54,27 @@
  * created from a layout resource file}, then it is considered safe to un-parent
  * the starting scene view in order to fade it out.</p>
  *
- * <p>Unlike the platform version, this does not support use in XML resources.</p>
+ * <p>A Fade transition can be described in a resource file by using the
+ * tag <code>fade</code>, along with the standard
+ * attributes of {@code Fade} and {@link Transition}.</p>
  */
 public class Fade extends Visibility {
 
     private static final String LOG_TAG = "Fade";
-    private static final String PROPNAME_SCREEN_X = "android:fade:screenX";
-    private static final String PROPNAME_SCREEN_Y = "android:fade:screenY";
 
     /**
      * Fading mode used in {@link #Fade(int)} to make the transition
      * operate on targets that are appearing. Maybe be combined with
      * {@link #OUT} to fade both in and out.
      */
-    public static final int IN = 0x1;
+    public static final int IN = Visibility.MODE_IN;
 
     /**
      * Fading mode used in {@link #Fade(int)} to make the transition
      * operate on targets that are disappearing. Maybe be combined with
      * {@link #IN} to fade both in and out.
      */
-    public static final int OUT = 0x2;
-
-    private int mFadingMode;
+    public static final int OUT = Visibility.MODE_OUT;
 
     /**
      * Constructs a Fade transition that will fade targets in
@@ -82,259 +84,111 @@
      *                   {@link #IN} and {@link #OUT}.
      */
     public Fade(int fadingMode) {
-        mFadingMode = fadingMode;
+        setMode(fadingMode);
     }
 
     /**
      * Constructs a Fade transition that will fade targets in and out.
      */
     public Fade() {
-        this(IN | OUT);
+    }
+
+    public Fade(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.FADE);
+        @Mode
+        int fadingMode = TypedArrayUtils.getNamedInt(a, (XmlResourceParser) attrs, "fadingMode",
+                Styleable.Fade.FADING_MODE, getMode());
+        setMode(fadingMode);
+        a.recycle();
     }
 
     /**
      * Utility method to handle creating and running the Animator.
      */
-    private Animator createAnimation(View view, float startAlpha, float endAlpha,
-            AnimatorListenerAdapter listener) {
+    private Animator createAnimation(View view, float startAlpha, float endAlpha) {
         if (startAlpha == endAlpha) {
-            // run listener if we're noop'ing the animation, to get the end-state results now
-            if (listener != null) {
-                listener.onAnimationEnd(null);
-            }
             return null;
         }
-        final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", startAlpha,
+        ViewUtils.setTransitionAlpha(view, startAlpha);
+        final ObjectAnimator anim = ObjectAnimator.ofFloat(view, ViewUtils.TRANSITION_ALPHA,
                 endAlpha);
         if (DBG) {
             Log.d(LOG_TAG, "Created animator " + anim);
         }
-        if (listener != null) {
-            anim.addListener(listener);
-        }
+        FadeAnimatorListener listener = new FadeAnimatorListener(view);
+        anim.addListener(listener);
+        AnimatorUtils.addPauseListener(anim, listener);
         return anim;
     }
 
-    private void captureValues(TransitionValues transitionValues) {
-        int[] loc = new int[2];
-        transitionValues.view.getLocationOnScreen(loc);
-        transitionValues.values.put(PROPNAME_SCREEN_X, loc[0]);
-        transitionValues.values.put(PROPNAME_SCREEN_Y, loc[1]);
-    }
-
     @Override
-    public void captureStartValues(@NonNull TransitionValues transitionValues) {
-        super.captureStartValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    @Override
-    public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues, int startVisibility,
-            TransitionValues endValues, int endVisibility) {
-        if ((mFadingMode & IN) != IN || endValues == null) {
-            return null;
-        }
-        final View endView = endValues.view;
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues,
+            TransitionValues endValues) {
         if (DBG) {
             View startView = (startValues != null) ? startValues.view : null;
             Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = "
-                    + startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
+                    + startView + ", " + view);
         }
-        endView.setAlpha(0);
-        TransitionListener transitionListener = new TransitionListenerAdapter() {
-            boolean mCanceled = false;
-
-            float mPausedAlpha;
-
-            @Override
-            public void onTransitionCancel(@NonNull Transition transition) {
-                endView.setAlpha(1);
-                mCanceled = true;
-            }
-
-            @Override
-            public void onTransitionEnd(@NonNull Transition transition) {
-                if (!mCanceled) {
-                    endView.setAlpha(1);
-                }
-            }
-
-            @Override
-            public void onTransitionPause(@NonNull Transition transition) {
-                mPausedAlpha = endView.getAlpha();
-                endView.setAlpha(1);
-            }
-
-            @Override
-            public void onTransitionResume(@NonNull Transition transition) {
-                endView.setAlpha(mPausedAlpha);
-            }
-        };
-        addListener(transitionListener);
-        return createAnimation(endView, 0, 1, null);
+        return createAnimation(view, 0, 1);
     }
 
     @Override
-    public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues,
-            int startVisibility, TransitionValues endValues, int endVisibility) {
-        if ((mFadingMode & OUT) != OUT) {
-            return null;
+    public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues,
+            TransitionValues endValues) {
+        return createAnimation(view, 1, 0);
+    }
+
+    private static class FadeAnimatorListener extends AnimatorListenerAdapter {
+
+        private final View mView;
+        private boolean mCanceled = false;
+        private float mPausedAlpha = -1;
+        private boolean mLayerTypeChanged = false;
+
+        FadeAnimatorListener(View view) {
+            mView = view;
         }
-        View view = null;
-        View startView = (startValues != null) ? startValues.view : null;
-        View endView = (endValues != null) ? endValues.view : null;
-        if (DBG) {
-            Log.d(LOG_TAG, "Fade.onDisappear: startView, startVis, endView, endVis = "
-                    + startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
-        }
-        View overlayView = null;
-        View viewToKeep = null;
-        if (endView == null || endView.getParent() == null) {
-            if (endView != null) {
-                // endView was removed from its parent - add it to the overlay
-                view = overlayView = endView;
-            } else if (startView != null) {
-                // endView does not exist. Use startView only under certain
-                // conditions, because placing a view in an overlay necessitates
-                // it being removed from its current parent
-                if (startView.getParent() == null) {
-                    // no parent - safe to use
-                    view = overlayView = startView;
-                } else if (startView.getParent() instanceof View
-                        && startView.getParent().getParent() == null) {
-                    View startParent = (View) startView.getParent();
-                    int id = startParent.getId();
-                    if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
-                        // no parent, but its parent is unparented  but the parent
-                        // hierarchy has been replaced by a new hierarchy with the same id
-                        // and it is safe to un-parent startView
-                        view = overlayView = startView;
-                    }
-                }
-            }
-        } else {
-            // visibility change
-            if (endVisibility == View.INVISIBLE) {
-                view = endView;
-                viewToKeep = view;
-            } else {
-                // Becoming GONE
-                if (startView == endView) {
-                    view = endView;
-                    viewToKeep = view;
-                } else {
-                    view = startView;
-                    overlayView = view;
-                }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            if (ViewCompat.hasOverlappingRendering(mView)
+                    && mView.getLayerType() == View.LAYER_TYPE_NONE) {
+                mLayerTypeChanged = true;
+                mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             }
         }
-        final int finalVisibility = endVisibility;
-        // TODO: add automatic facility to Visibility superclass for keeping views around
-        if (overlayView != null) {
-            // TODO: Need to do this for general case of adding to overlay
-            int screenX = (Integer) startValues.values.get(PROPNAME_SCREEN_X);
-            int screenY = (Integer) startValues.values.get(PROPNAME_SCREEN_Y);
-            int[] loc = new int[2];
-            sceneRoot.getLocationOnScreen(loc);
-            ViewCompat.offsetLeftAndRight(overlayView, (screenX - loc[0]) - overlayView.getLeft());
-            ViewCompat.offsetTopAndBottom(overlayView, (screenY - loc[1]) - overlayView.getTop());
-            ViewGroupUtils.getOverlay(sceneRoot).add(overlayView);
-            // TODO: add automatic facility to Visibility superclass for keeping views around
-            final float startAlpha = 1;
-            float endAlpha = 0;
-            final View finalView = view;
-            final View finalOverlayView = overlayView;
-            final View finalViewToKeep = viewToKeep;
-            final ViewGroup finalSceneRoot = sceneRoot;
-            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    finalView.setAlpha(startAlpha);
-                    // TODO: restore view offset from overlay repositioning
-                    if (finalViewToKeep != null) {
-                        finalViewToKeep.setVisibility(finalVisibility);
-                    }
-                    if (finalOverlayView != null) {
-                        ViewGroupUtils.getOverlay(finalSceneRoot)
-                                .remove(finalOverlayView);
-                    }
-                }
-//
-//                @Override
-//                public void onAnimationPause(Animator animation) {
-//                    if (finalOverlayView != null) {
-//                        finalSceneRoot.getOverlay().remove(finalOverlayView);
-//                    }
-//                }
-//
-//                @Override
-//                public void onAnimationResume(Animator animation) {
-//                    if (finalOverlayView != null) {
-//                        finalSceneRoot.getOverlay().add(finalOverlayView);
-//                    }
-//                }
-            };
-            return createAnimation(view, startAlpha, endAlpha, endListener);
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCanceled = true;
+            if (mPausedAlpha >= 0) {
+                ViewUtils.setTransitionAlpha(mView, mPausedAlpha);
+            }
         }
-        if (viewToKeep != null) {
-            // TODO: find a different way to do this, like just changing the view to be
-            // VISIBLE for the duration of the transition
-            viewToKeep.setVisibility((View.VISIBLE));
-            // TODO: add automatic facility to Visibility superclass for keeping views around
-            final float startAlpha = 1;
-            float endAlpha = 0;
-            final View finalView = view;
-            final View finalOverlayView = overlayView;
-            final View finalViewToKeep = viewToKeep;
-            final ViewGroup finalSceneRoot = sceneRoot;
-            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
-                boolean mCanceled = false;
 
-                float mPausedAlpha = -1;
-
-//                @Override
-//                public void onAnimationPause(Animator animation) {
-//                    if (finalViewToKeep != null && !mCanceled) {
-//                        finalViewToKeep.setVisibility(finalVisibility);
-//                    }
-//                    mPausedAlpha = finalView.getAlpha();
-//                    finalView.setAlpha(startAlpha);
-//                }
-//
-//                @Override
-//                public void onAnimationResume(Animator animation) {
-//                    if (finalViewToKeep != null && !mCanceled) {
-//                        finalViewToKeep.setVisibility(View.VISIBLE);
-//                    }
-//                    finalView.setAlpha(mPausedAlpha);
-//                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    mCanceled = true;
-                    if (mPausedAlpha >= 0) {
-                        finalView.setAlpha(mPausedAlpha);
-                    }
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (!mCanceled) {
-                        finalView.setAlpha(startAlpha);
-                    }
-                    // TODO: restore view offset from overlay repositioning
-                    if (finalViewToKeep != null && !mCanceled) {
-                        finalViewToKeep.setVisibility(finalVisibility);
-                    }
-                    if (finalOverlayView != null) {
-                        ViewGroupUtils.getOverlay(finalSceneRoot)
-                                .remove(finalOverlayView);
-                    }
-                }
-            };
-            return createAnimation(view, startAlpha, endAlpha, endListener);
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (!mCanceled) {
+                ViewUtils.setTransitionAlpha(mView, 1);
+            }
+            if (mLayerTypeChanged) {
+                mView.setLayerType(View.LAYER_TYPE_NONE, null);
+            }
         }
-        return null;
+
+        @Override
+        public void onAnimationPause(Animator animation) {
+            mPausedAlpha = ViewUtils.getTransitionAlpha(mView);
+            ViewUtils.setTransitionAlpha(mView, 1);
+        }
+
+        @Override
+        public void onAnimationResume(Animator animation) {
+            ViewUtils.setTransitionAlpha(mView, mPausedAlpha);
+        }
+
     }
 
 }
diff --git a/transition/src/android/support/transition/ObjectAnimatorUtils.java b/transition/src/android/support/transition/ObjectAnimatorUtils.java
new file mode 100644
index 0000000..10ae3a6
--- /dev/null
+++ b/transition/src/android/support/transition/ObjectAnimatorUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.ObjectAnimator;
+import android.graphics.Path;
+import android.os.Build;
+import android.util.Property;
+
+class ObjectAnimatorUtils {
+
+    private static final ObjectAnimatorUtilsImpl IMPL;
+
+    static {
+        if (Build.VERSION.SDK_INT >= 21) {
+            IMPL = new ObjectAnimatorUtilsApi21();
+        } else {
+            IMPL = new ObjectAnimatorUtilsApi14();
+        }
+    }
+
+    static <T> ObjectAnimator ofInt(T target, String xPropertyName, String yPropertyName,
+            Path path) {
+        return IMPL.ofInt(target, xPropertyName, yPropertyName, path);
+    }
+
+    static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
+            Property<T, Integer> yProperty, Path path) {
+        return IMPL.ofInt(target, xProperty, yProperty, path);
+    }
+
+    static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
+            Property<T, Float> yProperty, Path path) {
+        return IMPL.ofFloat(target, xProperty, yProperty, path);
+    }
+
+}
diff --git a/transition/src/android/support/transition/PathMotion.java b/transition/src/android/support/transition/PathMotion.java
new file mode 100644
index 0000000..b537a3a
--- /dev/null
+++ b/transition/src/android/support/transition/PathMotion.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.graphics.Path;
+
+/**
+ * This base class can be extended to provide motion along a Path to Transitions.
+ *
+ * <p>
+ * Transitions such as {@link android.transition.ChangeBounds} move Views, typically
+ * in a straight path between the start and end positions. Applications that desire to
+ * have these motions move in a curve can change how Views interpolate in two dimensions
+ * by extending PathMotion and implementing {@link #getPath(float, float, float, float)}.
+ * </p>
+ */
+public abstract class PathMotion {
+
+    public PathMotion() {
+    }
+
+    /**
+     * Provide a Path to interpolate between two points <code>(startX, startY)</code> and
+     * <code>(endX, endY)</code>. This allows controlled curved motion along two dimensions.
+     *
+     * @param startX The x coordinate of the starting point.
+     * @param startY The y coordinate of the starting point.
+     * @param endX   The x coordinate of the ending point.
+     * @param endY   The y coordinate of the ending point.
+     * @return A Path along which the points should be interpolated. The returned Path
+     * must start at point <code>(startX, startY)</code>, typically using
+     * {@link android.graphics.Path#moveTo(float, float)} and end at <code>(endX, endY)</code>.
+     */
+    public abstract Path getPath(float startX, float startY, float endX, float endY);
+}
diff --git a/transition/src/android/support/transition/PatternPathMotion.java b/transition/src/android/support/transition/PatternPathMotion.java
new file mode 100644
index 0000000..b4a14da
--- /dev/null
+++ b/transition/src/android/support/transition/PatternPathMotion.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+
+/**
+ * A PathMotion that takes a Path pattern and applies it to the separation between two points.
+ * The starting point of the Path will be moved to the origin and the end point will be scaled
+ * and rotated so that it matches with the target end point.
+ */
+public class PatternPathMotion extends PathMotion {
+
+    private Path mOriginalPatternPath;
+
+    private final Path mPatternPath = new Path();
+
+    private final Matrix mTempMatrix = new Matrix();
+
+    /**
+     * Constructs a PatternPathMotion with a straight-line pattern.
+     */
+    public PatternPathMotion() {
+        mPatternPath.lineTo(1, 0);
+        mOriginalPatternPath = mPatternPath;
+    }
+
+    /**
+     * Creates a PatternPathMotion with the Path defining a pattern of motion between two
+     * coordinates. The pattern will be translated, rotated, and scaled to fit between the start
+     * and end points. The pattern must not be empty and must have the end point differ from the
+     * start point.
+     *
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+     */
+    public PatternPathMotion(Path patternPath) {
+        setPatternPath(patternPath);
+    }
+
+    /**
+     * Returns the Path defining a pattern of motion between two coordinates.
+     * The pattern will be translated, rotated, and scaled to fit between the start and end points.
+     * The pattern must not be empty and must have the end point differ from the start point.
+     *
+     * @return the Path defining a pattern of motion between two coordinates.
+     */
+    public Path getPatternPath() {
+        return mOriginalPatternPath;
+    }
+
+    /**
+     * Sets the Path defining a pattern of motion between two coordinates.
+     * The pattern will be translated, rotated, and scaled to fit between the start and end points.
+     * The pattern must not be empty and must have the end point differ from the start point.
+     *
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+     */
+    public void setPatternPath(Path patternPath) {
+        PathMeasure pathMeasure = new PathMeasure(patternPath, false);
+        float length = pathMeasure.getLength();
+        float[] pos = new float[2];
+        pathMeasure.getPosTan(length, pos, null);
+        float endX = pos[0];
+        float endY = pos[1];
+        pathMeasure.getPosTan(0, pos, null);
+        float startX = pos[0];
+        float startY = pos[1];
+
+        if (startX == endX && startY == endY) {
+            throw new IllegalArgumentException("pattern must not end at the starting point");
+        }
+
+        mTempMatrix.setTranslate(-startX, -startY);
+        float dx = endX - startX;
+        float dy = endY - startY;
+        float distance = distance(dx, dy);
+        float scale = 1 / distance;
+        mTempMatrix.postScale(scale, scale);
+        double angle = Math.atan2(dy, dx);
+        mTempMatrix.postRotate((float) Math.toDegrees(-angle));
+        patternPath.transform(mTempMatrix, mPatternPath);
+        mOriginalPatternPath = patternPath;
+    }
+
+    @Override
+    public Path getPath(float startX, float startY, float endX, float endY) {
+        float dx = endX - startX;
+        float dy = endY - startY;
+        float length = distance(dx, dy);
+        double angle = Math.atan2(dy, dx);
+
+        mTempMatrix.setScale(length, length);
+        mTempMatrix.postRotate((float) Math.toDegrees(angle));
+        mTempMatrix.postTranslate(startX, startY);
+        Path path = new Path();
+        mPatternPath.transform(mTempMatrix, path);
+        return path;
+    }
+
+    private static float distance(float x, float y) {
+        return (float) Math.sqrt((x * x) + (y * y));
+    }
+
+}
diff --git a/transition/src/android/support/transition/PropertyValuesHolderUtils.java b/transition/src/android/support/transition/PropertyValuesHolderUtils.java
new file mode 100644
index 0000000..7a8eeb5
--- /dev/null
+++ b/transition/src/android/support/transition/PropertyValuesHolderUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.PropertyValuesHolder;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.os.Build;
+import android.util.Property;
+
+class PropertyValuesHolderUtils {
+
+    private static final PropertyValuesHolderUtilsImpl IMPL;
+
+    static {
+        if (Build.VERSION.SDK_INT >= 21) {
+            IMPL = new PropertyValuesHolderUtilsApi21();
+        } else {
+            IMPL = new PropertyValuesHolderUtilsApi14();
+        }
+    }
+
+    /**
+     * Constructs and returns a PropertyValuesHolder with a given property and
+     * a Path along which the values should be animated. This variant supports a
+     * <code>TypeConverter</code> to convert from <code>PointF</code> to the target
+     * type.
+     *
+     * @param property The property being animated. Should not be null.
+     * @param path     The Path along which the values should be animated.
+     * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
+     */
+    static PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path) {
+        return IMPL.ofPointF(property, path);
+    }
+
+}
diff --git a/transition/src/android/support/transition/Styleable.java b/transition/src/android/support/transition/Styleable.java
new file mode 100644
index 0000000..8f1bc9a
--- /dev/null
+++ b/transition/src/android/support/transition/Styleable.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.annotation.SuppressLint;
+import android.support.annotation.StyleableRes;
+
+/**
+ * Copies of styleable ID values generated in the platform R.java.
+ */
+@SuppressLint("InlinedApi")
+interface Styleable {
+
+    @StyleableRes
+    int[] TRANSITION_TARGET = {
+            android.R.attr.targetClass,
+            android.R.attr.targetId,
+            android.R.attr.excludeId,
+            android.R.attr.excludeClass,
+            android.R.attr.targetName,
+            android.R.attr.excludeName,
+    };
+
+    interface TransitionTarget {
+        @StyleableRes
+        int TARGET_CLASS = 0;
+        @StyleableRes
+        int TARGET_ID = 1;
+        @StyleableRes
+        int EXCLUDE_ID = 2;
+        @StyleableRes
+        int EXCLUDE_CLASS = 3;
+        @StyleableRes
+        int TARGET_NAME = 4;
+        @StyleableRes
+        int EXCLUDE_NAME = 5;
+    }
+
+    @StyleableRes
+    int[] TRANSITION_MANAGER = {
+            android.R.attr.fromScene,
+            android.R.attr.toScene,
+            android.R.attr.transition,
+    };
+
+    interface TransitionManager {
+        @StyleableRes
+        int FROM_SCENE = 0;
+        @StyleableRes
+        int TO_SCENE = 1;
+        @StyleableRes
+        int TRANSITION = 2;
+    }
+
+    @StyleableRes
+    int[] TRANSITION = {
+            android.R.attr.interpolator,
+            android.R.attr.duration,
+            android.R.attr.startDelay,
+            android.R.attr.matchOrder,
+    };
+
+    interface Transition {
+        @StyleableRes
+        int INTERPOLATOR = 0;
+        @StyleableRes
+        int DURATION = 1;
+        @StyleableRes
+        int START_DELAY = 2;
+        @StyleableRes
+        int MATCH_ORDER = 3;
+    }
+
+    @StyleableRes
+    int[] VISIBILITY_TRANSITION = {
+            android.R.attr.transitionVisibilityMode,
+    };
+
+    interface VisibilityTransition {
+        @StyleableRes
+        int TRANSITION_VISIBILITY_MODE = 0;
+    }
+
+    @StyleableRes
+    int[] FADE = {
+            android.R.attr.fadingMode,
+    };
+
+    interface Fade {
+        @StyleableRes
+        int FADING_MODE = 0;
+    }
+
+    @StyleableRes
+    int[] TRANSITION_SET = {
+            android.R.attr.transitionOrdering,
+    };
+
+    interface TransitionSet {
+        @StyleableRes
+        int TRANSITION_ORDERING = 0;
+    }
+
+}
diff --git a/transition/src/android/support/transition/Transition.java b/transition/src/android/support/transition/Transition.java
index 02441ea..17b23ab 100644
--- a/transition/src/android/support/transition/Transition.java
+++ b/transition/src/android/support/transition/Transition.java
@@ -21,20 +21,28 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Path;
 import android.support.annotation.IdRes;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.TypedArrayUtils;
 import android.support.v4.util.ArrayMap;
 import android.support.v4.util.LongSparseArray;
 import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.InflateException;
 import android.view.SurfaceView;
 import android.view.TextureView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.widget.ListView;
 import android.widget.Spinner;
 
@@ -42,6 +50,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.StringTokenizer;
 
 /**
  * A Transition holds information about animations that will be run on its
@@ -65,7 +74,44 @@
  * with TextureView because they rely on {@link android.view.ViewOverlay}
  * functionality, which does not currently work with TextureView.</p>
  *
- * <p>Unlike the platform version, this does not support declaration by XML resources.</p>
+ * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
+ * directory. Transition resources consist of a tag name for one of the Transition
+ * subclasses along with attributes to define some of the attributes of that transition.
+ * For example, here is a minimal resource file that declares a {@link ChangeBounds}
+ * transition:</p>
+ *
+ * <pre>
+ *     &lt;changeBounds/&gt;
+ * </pre>
+ *
+ * <p>Note that attributes for the transition are not required, just as they are
+ * optional when declared in code; Transitions created from XML resources will use
+ * the same defaults as their code-created equivalents. Here is a slightly more
+ * elaborate example which declares a {@link TransitionSet} transition with
+ * {@link ChangeBounds} and {@link Fade} child transitions:</p>
+ *
+ * <pre>
+ *     &lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ *          android:transitionOrdering="sequential"&gt;
+ *         &lt;changeBounds/&gt;
+ *         &lt;fade android:fadingMode="fade_out"&gt;
+ *             &lt;targets&gt;
+ *                 &lt;target android:targetId="@id/grayscaleContainer"/&gt;
+ *             &lt;/targets&gt;
+ *         &lt;/fade&gt;
+ *     &lt;/transitionSet&gt;
+ * </pre>
+ *
+ * <p>In this example, the transitionOrdering attribute is used on the TransitionSet
+ * object to change from the default {@link TransitionSet#ORDERING_TOGETHER} behavior
+ * to be {@link TransitionSet#ORDERING_SEQUENTIAL} instead. Also, the {@link Fade}
+ * transition uses a fadingMode of {@link Fade#OUT} instead of the default
+ * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
+ * takes a set of {code target} tags, each of which lists a specific <code>targetId</code> which
+ * this transition acts upon. Use of targets is optional, but can be used to either limit the time
+ * spent checking attributes on unchanging views, or limiting the types of animations run on
+ * specific views. In this case, we know that only the <code>grayscaleContainer</code> will be
+ * disappearing, so we choose to limit the {@link Fade} transition to only that view.</p>
  */
 public abstract class Transition implements Cloneable {
 
@@ -106,6 +152,11 @@
     public @interface MatchOrder {
     }
 
+    private static final String MATCH_INSTANCE_STR = "instance";
+    private static final String MATCH_NAME_STR = "name";
+    private static final String MATCH_ID_STR = "id";
+    private static final String MATCH_ITEM_ID_STR = "itemId";
+
     private static final int[] DEFAULT_MATCH_ORDER = {
             MATCH_NAME,
             MATCH_INSTANCE,
@@ -113,6 +164,16 @@
             MATCH_ITEM_ID,
     };
 
+    private static final PathMotion STRAIGHT_PATH_MOTION = new PathMotion() {
+        @Override
+        public Path getPath(float startX, float startY, float endX, float endY) {
+            Path path = new Path();
+            path.moveTo(startX, startY);
+            path.lineTo(endX, endY);
+            return path;
+        }
+    };
+
     private String mName = getClass().getName();
 
     private long mStartDelay = -1;
@@ -177,6 +238,10 @@
     // transitionNames.
     private ArrayMap<String, String> mNameOverrides;
 
+    // The function used to interpolate along two-dimensional points. Typically used
+    // for adding curves to x/y View motion.
+    private PathMotion mPathMotion = STRAIGHT_PATH_MOTION;
+
     /**
      * Constructs a Transition object with no target objects. A transition with
      * no targets defaults to running on all target objects in the scene hierarchy
@@ -187,6 +252,71 @@
     }
 
     /**
+     * Perform inflation from XML and apply a class-specific base style from a
+     * theme attribute or style resource. This constructor of Transition allows
+     * subclasses to use their own base style when they are inflating.
+     *
+     * @param context The Context the transition is running in, through which it can
+     *                access the current theme, resources, etc.
+     * @param attrs   The attributes of the XML tag that is inflating the transition.
+     */
+    public Transition(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.TRANSITION);
+        XmlResourceParser parser = (XmlResourceParser) attrs;
+        long duration = TypedArrayUtils.getNamedInt(a, parser, "duration",
+                Styleable.Transition.DURATION, -1);
+        if (duration >= 0) {
+            setDuration(duration);
+        }
+        long startDelay = TypedArrayUtils.getNamedInt(a, parser, "startDelay",
+                Styleable.Transition.START_DELAY, -1);
+        if (startDelay > 0) {
+            setStartDelay(startDelay);
+        }
+        final int resId = TypedArrayUtils.getNamedResourceId(a, parser, "interpolator",
+                Styleable.Transition.INTERPOLATOR, 0);
+        if (resId > 0) {
+            setInterpolator(AnimationUtils.loadInterpolator(context, resId));
+        }
+        String matchOrder = TypedArrayUtils.getNamedString(a, parser, "matchOrder",
+                Styleable.Transition.MATCH_ORDER);
+        if (matchOrder != null) {
+            setMatchOrder(parseMatchOrder(matchOrder));
+        }
+        a.recycle();
+    }
+
+    @MatchOrder
+    private static int[] parseMatchOrder(String matchOrderString) {
+        StringTokenizer st = new StringTokenizer(matchOrderString, ",");
+        @MatchOrder
+        int[] matches = new int[st.countTokens()];
+        int index = 0;
+        while (st.hasMoreTokens()) {
+            String token = st.nextToken().trim();
+            if (MATCH_ID_STR.equalsIgnoreCase(token)) {
+                matches[index] = Transition.MATCH_ID;
+            } else if (MATCH_INSTANCE_STR.equalsIgnoreCase(token)) {
+                matches[index] = Transition.MATCH_INSTANCE;
+            } else if (MATCH_NAME_STR.equalsIgnoreCase(token)) {
+                matches[index] = Transition.MATCH_NAME;
+            } else if (MATCH_ITEM_ID_STR.equalsIgnoreCase(token)) {
+                matches[index] = Transition.MATCH_ITEM_ID;
+            } else if (token.isEmpty()) {
+                @MatchOrder
+                int[] smallerMatches = new int[matches.length - 1];
+                System.arraycopy(matches, 0, smallerMatches, 0, index);
+                matches = smallerMatches;
+                index--;
+            } else {
+                throw new InflateException("Unknown match type in matchOrder: '" + token + "'");
+            }
+            index++;
+        }
+        return matches;
+    }
+
+    /**
      * Sets the duration of this transition. By default, there is no duration
      * (indicated by a negative number), which means that the Animator created by
      * the transition will have its own specified duration. If the duration of a
@@ -1074,14 +1204,13 @@
      * id, their instance reference, their transitionName, or by the Class of that view
      * (eg, {@link Spinner}).</p>
      *
+     * @param targetName The name of a target to ignore when running this transition.
+     * @param exclude    Whether to add the target to or remove the target from the
+     *                   current list of excluded targets.
+     * @return This transition object.
      * @see #excludeTarget(View, boolean)
      * @see #excludeTarget(int, boolean)
      * @see #excludeTarget(Class, boolean)
-     *
-     * @param targetName The name of a target to ignore when running this transition.
-     * @param exclude Whether to add the target to or remove the target from the
-     * current list of excluded targets.
-     * @return This transition object.
      */
     @NonNull
     public Transition excludeTarget(@NonNull String targetName, boolean exclude) {
@@ -1863,6 +1992,43 @@
         return this;
     }
 
+    /**
+     * Sets the algorithm used to calculate two-dimensional interpolation.
+     * <p>
+     * Transitions such as {@link android.transition.ChangeBounds} move Views, typically
+     * in a straight path between the start and end positions. Applications that desire to
+     * have these motions move in a curve can change how Views interpolate in two dimensions
+     * by extending PathMotion and implementing
+     * {@link android.transition.PathMotion#getPath(float, float, float, float)}.
+     * </p>
+     *
+     * @param pathMotion Algorithm object to use for determining how to interpolate in two
+     *                   dimensions. If null, a straight-path algorithm will be used.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
+     */
+    public void setPathMotion(PathMotion pathMotion) {
+        if (pathMotion == null) {
+            mPathMotion = STRAIGHT_PATH_MOTION;
+        } else {
+            mPathMotion = pathMotion;
+        }
+    }
+
+    /**
+     * Returns the algorithm object used to interpolate along two dimensions. This is typically
+     * used to determine the View motion between two points.
+     *
+     * @return The algorithm object used to interpolate along two dimensions.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
+     */
+    public PathMotion getPathMotion() {
+        return mPathMotion;
+    }
+
     Transition setSceneRoot(ViewGroup sceneRoot) {
         mSceneRoot = sceneRoot;
         return this;
diff --git a/transition/src/android/support/transition/TransitionInflater.java b/transition/src/android/support/transition/TransitionInflater.java
new file mode 100644
index 0000000..9bdfdf7
--- /dev/null
+++ b/transition/src/android/support/transition/TransitionInflater.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.support.annotation.NonNull;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v4.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.InflateException;
+import android.view.ViewGroup;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+
+/**
+ * This class inflates scenes and transitions from resource files.
+ */
+public class TransitionInflater {
+
+    private static final Class<?>[] CONSTRUCTOR_SIGNATURE =
+            new Class[]{Context.class, AttributeSet.class};
+    private static final ArrayMap<String, Constructor> CONSTRUCTORS = new ArrayMap<>();
+
+    private final Context mContext;
+
+    private TransitionInflater(@NonNull Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Obtains the TransitionInflater from the given context.
+     */
+    public static TransitionInflater from(Context context) {
+        return new TransitionInflater(context);
+    }
+
+    /**
+     * Loads a {@link Transition} object from a resource
+     *
+     * @param resource The resource id of the transition to load
+     * @return The loaded Transition object
+     * @throws android.content.res.Resources.NotFoundException when the
+     *                                                         transition cannot be loaded
+     */
+    public Transition inflateTransition(int resource) {
+        XmlResourceParser parser = mContext.getResources().getXml(resource);
+        try {
+            return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null);
+        } catch (XmlPullParserException e) {
+            throw new InflateException(e.getMessage(), e);
+        } catch (IOException e) {
+            throw new InflateException(
+                    parser.getPositionDescription() + ": " + e.getMessage(), e);
+        } finally {
+            parser.close();
+        }
+    }
+
+    /**
+     * Loads a {@link TransitionManager} object from a resource
+     *
+     * @param resource The resource id of the transition manager to load
+     * @return The loaded TransitionManager object
+     * @throws android.content.res.Resources.NotFoundException when the
+     *                                                         transition manager cannot be loaded
+     */
+    public TransitionManager inflateTransitionManager(int resource, ViewGroup sceneRoot) {
+        XmlResourceParser parser = mContext.getResources().getXml(resource);
+        try {
+            return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot);
+        } catch (XmlPullParserException e) {
+            InflateException ex = new InflateException(e.getMessage());
+            ex.initCause(e);
+            throw ex;
+        } catch (IOException e) {
+            InflateException ex = new InflateException(
+                    parser.getPositionDescription()
+                            + ": " + e.getMessage());
+            ex.initCause(e);
+            throw ex;
+        } finally {
+            parser.close();
+        }
+    }
+
+    //
+    // Transition loading
+    //
+    private Transition createTransitionFromXml(XmlPullParser parser,
+            AttributeSet attrs, Transition parent)
+            throws XmlPullParserException, IOException {
+
+        Transition transition = null;
+
+        // Make sure we are on a start tag.
+        int type;
+        int depth = parser.getDepth();
+
+        TransitionSet transitionSet = (parent instanceof TransitionSet)
+                ? (TransitionSet) parent : null;
+
+        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+                && type != XmlPullParser.END_DOCUMENT) {
+
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            // TODO: Add more Transition types
+            String name = parser.getName();
+            if ("fade".equals(name)) {
+                transition = new Fade(mContext, attrs);
+            } else if ("changeBounds".equals(name)) {
+                transition = new ChangeBounds(mContext, attrs);
+            } else if ("autoTransition".equals(name)) {
+                transition = new AutoTransition(mContext, attrs);
+            } else if ("transitionSet".equals(name)) {
+                transition = new TransitionSet(mContext, attrs);
+            } else if ("transition".equals(name)) {
+                transition = (Transition) createCustom(attrs, Transition.class, "transition");
+            } else if ("targets".equals(name)) {
+                getTargetIds(parser, attrs, parent);
+            } else {
+                throw new RuntimeException("Unknown scene name: " + parser.getName());
+            }
+            if (transition != null) {
+                if (!parser.isEmptyElementTag()) {
+                    createTransitionFromXml(parser, attrs, transition);
+                }
+                if (transitionSet != null) {
+                    transitionSet.addTransition(transition);
+                    transition = null;
+                } else if (parent != null) {
+                    throw new InflateException("Could not add transition to another transition.");
+                }
+            }
+        }
+
+        return transition;
+    }
+
+    private Object createCustom(AttributeSet attrs, Class expectedType, String tag) {
+        String className = attrs.getAttributeValue(null, "class");
+
+        if (className == null) {
+            throw new InflateException(tag + " tag must have a 'class' attribute");
+        }
+
+        try {
+            synchronized (CONSTRUCTORS) {
+                Constructor constructor = CONSTRUCTORS.get(className);
+                if (constructor == null) {
+                    Class<?> c = mContext.getClassLoader().loadClass(className)
+                            .asSubclass(expectedType);
+                    if (c != null) {
+                        constructor = c.getConstructor(CONSTRUCTOR_SIGNATURE);
+                        constructor.setAccessible(true);
+                        CONSTRUCTORS.put(className, constructor);
+                    }
+                }
+                //noinspection ConstantConditions
+                return constructor.newInstance(mContext, attrs);
+            }
+        } catch (Exception e) {
+            throw new InflateException("Could not instantiate " + expectedType + " class "
+                    + className, e);
+        }
+    }
+
+    private void getTargetIds(XmlPullParser parser,
+            AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException {
+
+        // Make sure we are on a start tag.
+        int type;
+        int depth = parser.getDepth();
+
+        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+                && type != XmlPullParser.END_DOCUMENT) {
+
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            String name = parser.getName();
+            if (name.equals("target")) {
+                TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_TARGET);
+                int id = TypedArrayUtils.getNamedResourceId(a, parser, "targetId",
+                        Styleable.TransitionTarget.TARGET_ID, 0);
+                String transitionName;
+                if (id != 0) {
+                    transition.addTarget(id);
+                } else if ((id = TypedArrayUtils.getNamedResourceId(a, parser, "excludeId",
+                        Styleable.TransitionTarget.EXCLUDE_ID, 0)) != 0) {
+                    transition.excludeTarget(id, true);
+                } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser, "targetName",
+                        Styleable.TransitionTarget.TARGET_NAME)) != null) {
+                    transition.addTarget(transitionName);
+                } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser,
+                        "excludeName", Styleable.TransitionTarget.EXCLUDE_NAME)) != null) {
+                    transition.excludeTarget(transitionName, true);
+                } else {
+                    String className = TypedArrayUtils.getNamedString(a, parser,
+                            "excludeClass", Styleable.TransitionTarget.EXCLUDE_CLASS);
+                    try {
+                        if (className != null) {
+                            Class clazz = Class.forName(className);
+                            transition.excludeTarget(clazz, true);
+                        } else if ((className = TypedArrayUtils.getNamedString(a, parser,
+                                "targetClass", Styleable.TransitionTarget.TARGET_CLASS)) != null) {
+                            Class clazz = Class.forName(className);
+                            transition.addTarget(clazz);
+                        }
+                    } catch (ClassNotFoundException e) {
+                        a.recycle();
+                        throw new RuntimeException("Could not create " + className, e);
+                    }
+                }
+                a.recycle();
+            } else {
+                throw new RuntimeException("Unknown scene name: " + parser.getName());
+            }
+        }
+    }
+
+    //
+    // TransitionManager loading
+    //
+
+    private TransitionManager createTransitionManagerFromXml(XmlPullParser parser,
+            AttributeSet attrs, ViewGroup sceneRoot) throws XmlPullParserException, IOException {
+
+        // Make sure we are on a start tag.
+        int type;
+        int depth = parser.getDepth();
+        TransitionManager transitionManager = null;
+
+        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+                && type != XmlPullParser.END_DOCUMENT) {
+
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            String name = parser.getName();
+            if (name.equals("transitionManager")) {
+                transitionManager = new TransitionManager();
+            } else if (name.equals("transition") && (transitionManager != null)) {
+                loadTransition(attrs, parser, sceneRoot, transitionManager);
+            } else {
+                throw new RuntimeException("Unknown scene name: " + parser.getName());
+            }
+        }
+        return transitionManager;
+    }
+
+    private void loadTransition(AttributeSet attrs, XmlPullParser parser, ViewGroup sceneRoot,
+            TransitionManager transitionManager) throws Resources.NotFoundException {
+
+        TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_MANAGER);
+        int transitionId = TypedArrayUtils.getNamedResourceId(a, parser, "transition",
+                Styleable.TransitionManager.TRANSITION, -1);
+        int fromId = TypedArrayUtils.getNamedResourceId(a, parser, "fromScene",
+                Styleable.TransitionManager.FROM_SCENE, -1);
+        Scene fromScene = (fromId < 0) ? null : Scene.getSceneForLayout(sceneRoot, fromId,
+                mContext);
+        int toId = TypedArrayUtils.getNamedResourceId(a, parser, "toScene",
+                Styleable.TransitionManager.TO_SCENE, -1);
+        Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext);
+
+        if (transitionId >= 0) {
+            Transition transition = inflateTransition(transitionId);
+            if (transition != null) {
+                if (toScene == null) {
+                    throw new RuntimeException("No toScene for transition ID " + transitionId);
+                }
+                if (fromScene == null) {
+                    transitionManager.setTransition(toScene, transition);
+                } else {
+                    transitionManager.setTransition(fromScene, toScene, transition);
+                }
+            }
+        }
+        a.recycle();
+    }
+
+}
diff --git a/transition/src/android/support/transition/TransitionManager.java b/transition/src/android/support/transition/TransitionManager.java
index 16ef845..508e4a6 100644
--- a/transition/src/android/support/transition/TransitionManager.java
+++ b/transition/src/android/support/transition/TransitionManager.java
@@ -16,6 +16,7 @@
 
 package android.support.transition;
 
+import android.content.Context;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.util.ArrayMap;
@@ -39,7 +40,40 @@
  * only necessary if the application wants different transition behavior
  * in these situations.
  *
- * <p>Unlike the platform version, this does not support declaration by XML resources.</p>
+ * <p>TransitionManagers can be declared in XML resource files inside the
+ * <code>res/transition</code> directory. TransitionManager resources consist of
+ * the <code>transitionManager</code>tag name, containing one or more
+ * <code>transition</code> tags, each of which describe the relationship of
+ * that transition to the from/to scene information in that tag.
+ * For example, here is a resource file that declares several scene
+ * transitions:</p>
+ *
+ * <pre>
+ *     &lt;transitionManager xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ *         &lt;transition android:fromScene="@layout/transition_scene1"
+ *                     android:toScene="@layout/transition_scene2"
+ *                     android:transition="@transition/changebounds"/&gt;
+ *         &lt;transition android:fromScene="@layout/transition_scene2"
+ *                     android:toScene="@layout/transition_scene1"
+ *                     android:transition="@transition/changebounds"/&gt;
+ *         &lt;transition android:toScene="@layout/transition_scene3"
+ *                     android:transition="@transition/changebounds_fadein_together"/&gt;
+ *         &lt;transition android:fromScene="@layout/transition_scene3"
+ *                     android:toScene="@layout/transition_scene1"
+ *                     android:transition="@transition/changebounds_fadeout_sequential"/&gt;
+ *         &lt;transition android:fromScene="@layout/transition_scene3"
+ *                     android:toScene="@layout/transition_scene2"
+ *                     android:transition="@transition/changebounds_fadeout_sequential"/&gt;
+ *     &lt;/transitionManager&gt;
+ * </pre>
+ *
+ * <p>For each of the <code>fromScene</code> and <code>toScene</code> attributes,
+ * there is a reference to a standard XML layout file. This is equivalent to
+ * creating a scene from a layout in code by calling
+ * {@link Scene#getSceneForLayout(ViewGroup, int, Context)}. For the
+ * <code>transition</code> attribute, there is a reference to a resource
+ * file in the <code>res/transition</code> directory which describes that
+ * transition.</p>
  */
 public class TransitionManager {
 
diff --git a/transition/src/android/support/transition/TransitionSet.java b/transition/src/android/support/transition/TransitionSet.java
index 66f8109..f1d83e0 100644
--- a/transition/src/android/support/transition/TransitionSet.java
+++ b/transition/src/android/support/transition/TransitionSet.java
@@ -19,11 +19,16 @@
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
 import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
 import android.support.annotation.IdRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.TypedArrayUtils;
 import android.util.AndroidRuntimeException;
+import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -37,7 +42,20 @@
  * uses a TransitionSet to sequentially play a Fade(Fade.OUT), followed by
  * a {@link ChangeBounds}, followed by a Fade(Fade.OUT) transition.
  *
- * <p>Unlike the platform version, this does not support declaration by XML resources.</p>
+ * <p>A TransitionSet can be described in a resource file by using the
+ * tag <code>transitionSet</code>, along with the standard
+ * attributes of {@code TransitionSet} and {@link Transition}. Child transitions of the
+ * TransitionSet object can be loaded by adding those child tags inside the
+ * enclosing <code>transitionSet</code> tag. For example, the following xml
+ * describes a TransitionSet that plays a Fade and then a ChangeBounds
+ * transition on the affected view targets:</p>
+ * <pre>
+ *     &lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ *             android:ordering="sequential"&gt;
+ *         &lt;fade/&gt;
+ *         &lt;changeBounds/&gt;
+ *     &lt;/transitionSet&gt;
+ * </pre>
  */
 public class TransitionSet extends Transition {
 
@@ -69,6 +87,16 @@
     public TransitionSet() {
     }
 
+    public TransitionSet(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.TRANSITION_SET);
+        int ordering = TypedArrayUtils.getNamedInt(a, (XmlResourceParser) attrs,
+                "transitionOrdering", Styleable.TransitionSet.TRANSITION_ORDERING,
+                TransitionSet.ORDERING_TOGETHER);
+        setOrdering(ordering);
+        a.recycle();
+    }
+
     /**
      * Sets the play order of this set's child transitions.
      *
@@ -305,6 +333,14 @@
         return (TransitionSet) super.removeListener(listener);
     }
 
+    @Override
+    public void setPathMotion(PathMotion pathMotion) {
+        super.setPathMotion(pathMotion);
+        for (int i = 0; i < mTransitions.size(); i++) {
+            mTransitions.get(i).setPathMotion(pathMotion);
+        }
+    }
+
     /**
      * Removes the specified child transition from this set.
      *
diff --git a/transition/src/android/support/transition/TransitionUtils.java b/transition/src/android/support/transition/TransitionUtils.java
new file mode 100644
index 0000000..e3770b8
--- /dev/null
+++ b/transition/src/android/support/transition/TransitionUtils.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+class TransitionUtils {
+
+    private static final int MAX_IMAGE_SIZE = 1024 * 1024;
+
+    /**
+     * Creates a View using the bitmap copy of <code>view</code>. If <code>view</code> is large,
+     * the copy will use a scaled bitmap of the given view.
+     *
+     * @param sceneRoot The ViewGroup in which the view copy will be displayed.
+     * @param view      The view to create a copy of.
+     * @param parent    The parent of view.
+     */
+    static View copyViewImage(ViewGroup sceneRoot, View view, View parent) {
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(-parent.getScrollX(), -parent.getScrollY());
+        ViewUtils.transformMatrixToGlobal(view, matrix);
+        ViewUtils.transformMatrixToLocal(sceneRoot, matrix);
+        RectF bounds = new RectF(0, 0, view.getWidth(), view.getHeight());
+        matrix.mapRect(bounds);
+        int left = Math.round(bounds.left);
+        int top = Math.round(bounds.top);
+        int right = Math.round(bounds.right);
+        int bottom = Math.round(bounds.bottom);
+
+        ImageView copy = new ImageView(view.getContext());
+        copy.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        Bitmap bitmap = createViewBitmap(view, matrix, bounds);
+        if (bitmap != null) {
+            copy.setImageBitmap(bitmap);
+        }
+        int widthSpec = View.MeasureSpec.makeMeasureSpec(right - left, View.MeasureSpec.EXACTLY);
+        int heightSpec = View.MeasureSpec.makeMeasureSpec(bottom - top, View.MeasureSpec.EXACTLY);
+        copy.measure(widthSpec, heightSpec);
+        copy.layout(left, top, right, bottom);
+        return copy;
+    }
+
+    /**
+     * Creates a Bitmap of the given view, using the Matrix matrix to transform to the local
+     * coordinates. <code>matrix</code> will be modified during the bitmap creation.
+     *
+     * <p>If the bitmap is large, it will be scaled uniformly down to at most 1MB size.</p>
+     *
+     * @param view   The view to create a bitmap for.
+     * @param matrix The matrix converting the view local coordinates to the coordinates that
+     *               the bitmap will be displayed in. <code>matrix</code> will be modified before
+     *               returning.
+     * @param bounds The bounds of the bitmap in the destination coordinate system (where the
+     *               view should be presented. Typically, this is matrix.mapRect(viewBounds);
+     * @return A bitmap of the given view or null if bounds has no width or height.
+     */
+    private static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds) {
+        Bitmap bitmap = null;
+        int bitmapWidth = Math.round(bounds.width());
+        int bitmapHeight = Math.round(bounds.height());
+        if (bitmapWidth > 0 && bitmapHeight > 0) {
+            float scale = Math.min(1f, ((float) MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight));
+            bitmapWidth *= scale;
+            bitmapHeight *= scale;
+            matrix.postTranslate(-bounds.left, -bounds.top);
+            matrix.postScale(scale, scale);
+            bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(bitmap);
+            canvas.concat(matrix);
+            view.draw(canvas);
+        }
+        return bitmap;
+    }
+
+    static Animator mergeAnimators(Animator animator1, Animator animator2) {
+        if (animator1 == null) {
+            return animator2;
+        } else if (animator2 == null) {
+            return animator1;
+        } else {
+            AnimatorSet animatorSet = new AnimatorSet();
+            animatorSet.playTogether(animator1, animator2);
+            return animatorSet;
+        }
+    }
+
+}
diff --git a/transition/src/android/support/transition/ViewUtils.java b/transition/src/android/support/transition/ViewUtils.java
index 52186d8..ac170cc 100644
--- a/transition/src/android/support/transition/ViewUtils.java
+++ b/transition/src/android/support/transition/ViewUtils.java
@@ -16,9 +16,14 @@
 
 package android.support.transition;
 
+import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.v4.view.ViewCompat;
+import android.util.Property;
 import android.view.View;
+import android.view.ViewParent;
 
 /**
  * Compatibility utilities for platform features of {@link View}.
@@ -28,7 +33,9 @@
     private static final ViewUtilsImpl IMPL;
 
     static {
-        if (Build.VERSION.SDK_INT >= 18) {
+        if (Build.VERSION.SDK_INT >= 19) {
+            IMPL = new ViewUtilsApi19();
+        } else if (Build.VERSION.SDK_INT >= 18) {
             IMPL = new ViewUtilsApi18();
         } else {
             IMPL = new ViewUtilsApi14();
@@ -36,6 +43,39 @@
     }
 
     /**
+     * A {@link Property} for animating transitionAlpha value of a View.
+     */
+    static final Property<View, Float> TRANSITION_ALPHA =
+            new Property<View, Float>(Float.class, "translationAlpha") {
+
+                @Override
+                public Float get(View view) {
+                    return getTransitionAlpha(view);
+                }
+
+                @Override
+                public void set(View view, Float alpha) {
+                    setTransitionAlpha(view, alpha);
+                }
+
+            };
+
+    static final Property<View, Rect> CLIP_BOUNDS =
+            new Property<View, Rect>(Rect.class, "clipBounds") {
+
+                @Override
+                public Rect get(View view) {
+                    return ViewCompat.getClipBounds(view);
+                }
+
+                @Override
+                public void set(View view, Rect clipBounds) {
+                    ViewCompat.setClipBounds(view, clipBounds);
+                }
+
+            };
+
+    /**
      * Backward-compatible {@link View#getOverlay()}.
      */
     static ViewOverlayImpl getOverlay(@NonNull View view) {
@@ -49,4 +89,57 @@
         return IMPL.getWindowId(view);
     }
 
+    static void setTransitionAlpha(@NonNull View view, float alpha) {
+        IMPL.setTransitionAlpha(view, alpha);
+    }
+
+    static float getTransitionAlpha(@NonNull View view) {
+        return IMPL.getTransitionAlpha(view);
+    }
+
+    /**
+     * Modifies the input matrix such that it maps view-local coordinates to
+     * on-screen coordinates.
+     *
+     * @param view target view
+     * @param matrix input matrix to modify
+     */
+    static void transformMatrixToGlobal(@NonNull View view, @NonNull Matrix matrix) {
+        final ViewParent parent = view.getParent();
+        if (parent instanceof View) {
+            final View vp = (View) parent;
+            transformMatrixToGlobal(vp, matrix);
+            matrix.preTranslate(-vp.getScrollX(), -vp.getScrollY());
+        }
+        matrix.preTranslate(view.getLeft(), view.getTop());
+        final Matrix vm = view.getMatrix();
+        if (!vm.isIdentity()) {
+            matrix.preConcat(vm);
+        }
+    }
+
+    /**
+     * Modifies the input matrix such that it maps on-screen coordinates to
+     * view-local coordinates.
+     *
+     * @param view target view
+     * @param matrix input matrix to modify
+     */
+    static void transformMatrixToLocal(@NonNull View view, @NonNull Matrix matrix) {
+        final ViewParent parent = view.getParent();
+        if (parent instanceof View) {
+            final View vp = (View) parent;
+            transformMatrixToLocal(vp, matrix);
+            matrix.postTranslate(vp.getScrollX(), vp.getScrollY());
+        }
+        matrix.postTranslate(view.getLeft(), view.getTop());
+        final Matrix vm = view.getMatrix();
+        if (!vm.isIdentity()) {
+            final Matrix inverted = new Matrix();
+            if (vm.invert(inverted)) {
+                matrix.postConcat(inverted);
+            }
+        }
+    }
+
 }
diff --git a/transition/src/android/support/transition/Visibility.java b/transition/src/android/support/transition/Visibility.java
index 5522f6a..4f709c5 100644
--- a/transition/src/android/support/transition/Visibility.java
+++ b/transition/src/android/support/transition/Visibility.java
@@ -16,12 +16,25 @@
 
 package android.support.transition;
 
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * This transition tracks changes to the visibility of target views in the
  * start and end scenes. Visibility is determined not just by the
@@ -31,12 +44,36 @@
  * information to determine the specific animations to run when visibility
  * changes occur. Subclasses should implement one or both of the methods
  * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
- * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
+ * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
+ * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
+ * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
  */
 public abstract class Visibility extends Transition {
 
     private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
     private static final String PROPNAME_PARENT = "android:visibility:parent";
+    private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
+
+    /**
+     * Mode used in {@link #setMode(int)} to make the transition
+     * operate on targets that are appearing. Maybe be combined with
+     * {@link #MODE_OUT} to target Visibility changes both in and out.
+     */
+    public static final int MODE_IN = 0x1;
+
+    /**
+     * Mode used in {@link #setMode(int)} to make the transition
+     * operate on targets that are disappearing. Maybe be combined with
+     * {@link #MODE_IN} to target Visibility changes both in and out.
+     */
+    public static final int MODE_OUT = 0x2;
+
+    /** @hide */
+    @RestrictTo(LIBRARY_GROUP)
+    @IntDef(flag = true, value = {MODE_IN, MODE_OUT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Mode {
+    }
 
     private static final String[] sTransitionProperties = {
             PROPNAME_VISIBILITY,
@@ -52,9 +89,49 @@
         ViewGroup mEndParent;
     }
 
+    private int mMode = MODE_IN | MODE_OUT;
+
     public Visibility() {
     }
 
+    public Visibility(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.VISIBILITY_TRANSITION);
+        @Mode
+        int mode = TypedArrayUtils.getNamedInt(a, (XmlResourceParser) attrs,
+                "transitionVisibilityMode",
+                Styleable.VisibilityTransition.TRANSITION_VISIBILITY_MODE, 0);
+        a.recycle();
+        if (mode != 0) {
+            setMode(mode);
+        }
+    }
+
+    /**
+     * Changes the transition to support appearing and/or disappearing Views, depending
+     * on <code>mode</code>.
+     *
+     * @param mode The behavior supported by this transition, a combination of
+     *             {@link #MODE_IN} and {@link #MODE_OUT}.
+     */
+    public void setMode(@Mode int mode) {
+        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
+            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
+        }
+        mMode = mode;
+    }
+
+    /**
+     * Returns whether appearing and/or disappearing Views are supported.
+     *
+     * @return whether appearing and/or disappearing Views are supported. A combination of
+     * {@link #MODE_IN} and {@link #MODE_OUT}.
+     */
+    @Mode
+    public int getMode() {
+        return mMode;
+    }
+
     @Nullable
     @Override
     public String[] getTransitionProperties() {
@@ -65,6 +142,9 @@
         int visibility = transitionValues.view.getVisibility();
         transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
         transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
+        int[] loc = new int[2];
+        transitionValues.view.getLocationOnScreen(loc);
+        transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
     }
 
     @Override
@@ -107,14 +187,14 @@
         final VisibilityInfo visInfo = new VisibilityInfo();
         visInfo.mVisibilityChange = false;
         visInfo.mFadeIn = false;
-        if (startValues != null) {
+        if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
             visInfo.mStartVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
             visInfo.mStartParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
         } else {
             visInfo.mStartVisibility = -1;
             visInfo.mStartParent = null;
         }
-        if (endValues != null) {
+        if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
             visInfo.mEndVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
             visInfo.mEndParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
         } else {
@@ -145,11 +225,10 @@
                     }
                 }
             }
-        }
-        if (startValues == null) {
+        } else if (startValues == null && visInfo.mEndVisibility == View.VISIBLE) {
             visInfo.mFadeIn = true;
             visInfo.mVisibilityChange = true;
-        } else if (endValues == null) {
+        } else if (endValues == null && visInfo.mStartVisibility == View.VISIBLE) {
             visInfo.mFadeIn = false;
             visInfo.mVisibilityChange = true;
         }
@@ -161,24 +240,15 @@
     public Animator createAnimator(@NonNull ViewGroup sceneRoot,
             @Nullable TransitionValues startValues, @Nullable TransitionValues endValues) {
         VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
-        if (visInfo.mVisibilityChange) {
-            // Only transition views that are either targets of this transition
-            // or whose parent hierarchies remain stable between scenes
-            boolean isTarget = false;
-            if (mTargets.size() > 0 || mTargetIds.size() > 0) {
-                View startView = startValues != null ? startValues.view : null;
-                View endView = endValues != null ? endValues.view : null;
-                isTarget = isValidTarget(startView) || isValidTarget(endView);
-            }
-            if (isTarget || ((visInfo.mStartParent != null || visInfo.mEndParent != null))) {
-                if (visInfo.mFadeIn) {
-                    return onAppear(sceneRoot, startValues, visInfo.mStartVisibility,
-                            endValues, visInfo.mEndVisibility);
-                } else {
-                    return onDisappear(sceneRoot, startValues, visInfo.mStartVisibility,
-                            endValues, visInfo.mEndVisibility
-                    );
-                }
+        if (visInfo.mVisibilityChange
+                && (visInfo.mStartParent != null || visInfo.mEndParent != null)) {
+            if (visInfo.mFadeIn) {
+                return onAppear(sceneRoot, startValues, visInfo.mStartVisibility,
+                        endValues, visInfo.mEndVisibility);
+            } else {
+                return onDisappear(sceneRoot, startValues, visInfo.mStartVisibility,
+                        endValues, visInfo.mEndVisibility
+                );
             }
         }
         return null;
@@ -202,6 +272,42 @@
     @SuppressWarnings("UnusedParameters")
     public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
+        if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
+            return null;
+        }
+        if (startValues == null) {
+            View endParent = (View) endValues.view.getParent();
+            TransitionValues startParentValues = getMatchedTransitionValues(endParent,
+                    false);
+            TransitionValues endParentValues = getTransitionValues(endParent, false);
+            VisibilityInfo parentVisibilityInfo =
+                    getVisibilityChangeInfo(startParentValues, endParentValues);
+            if (parentVisibilityInfo.mVisibilityChange) {
+                return null;
+            }
+        }
+        return onAppear(sceneRoot, endValues.view, startValues, endValues);
+    }
+
+    /**
+     * The default implementation of this method returns a null Animator. Subclasses should
+     * override this method to make targets appear with the desired transition. The
+     * method should only be called from
+     * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+     *
+     * @param sceneRoot   The root of the transition hierarchy
+     * @param view        The View to make appear. This will be in the target scene's View
+     *                    hierarchy
+     *                    and
+     *                    will be VISIBLE.
+     * @param startValues The target values in the start scene
+     * @param endValues   The target values in the end scene
+     * @return An Animator to be started at the appropriate time in the
+     * overall transition for this scene change. A null value means no animation
+     * should be run.
+     */
+    public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+            TransitionValues endValues) {
         return null;
     }
 
@@ -223,6 +329,154 @@
     @SuppressWarnings("UnusedParameters")
     public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues,
             int startVisibility, TransitionValues endValues, int endVisibility) {
+        if ((mMode & MODE_OUT) != MODE_OUT) {
+            return null;
+        }
+
+        View startView = (startValues != null) ? startValues.view : null;
+        View endView = (endValues != null) ? endValues.view : null;
+        View overlayView = null;
+        View viewToKeep = null;
+        if (endView == null || endView.getParent() == null) {
+            if (endView != null) {
+                // endView was removed from its parent - add it to the overlay
+                overlayView = endView;
+            } else if (startView != null) {
+                // endView does not exist. Use startView only under certain
+                // conditions, because placing a view in an overlay necessitates
+                // it being removed from its current parent
+                if (startView.getParent() == null) {
+                    // no parent - safe to use
+                    overlayView = startView;
+                } else if (startView.getParent() instanceof View) {
+                    View startParent = (View) startView.getParent();
+                    TransitionValues startParentValues = getTransitionValues(startParent, true);
+                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
+                            true);
+                    VisibilityInfo parentVisibilityInfo =
+                            getVisibilityChangeInfo(startParentValues, endParentValues);
+                    if (!parentVisibilityInfo.mVisibilityChange) {
+                        overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
+                                startParent);
+                    } else if (startParent.getParent() == null) {
+                        int id = startParent.getId();
+                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
+                                && mCanRemoveViews) {
+                            // no parent, but its parent is unparented  but the parent
+                            // hierarchy has been replaced by a new hierarchy with the same id
+                            // and it is safe to un-parent startView
+                            overlayView = startView;
+                        }
+                    }
+                }
+            }
+        } else {
+            // visibility change
+            if (endVisibility == View.INVISIBLE) {
+                viewToKeep = endView;
+            } else {
+                // Becoming GONE
+                if (startView == endView) {
+                    viewToKeep = endView;
+                } else {
+                    overlayView = startView;
+                }
+            }
+        }
+        final int finalVisibility = endVisibility;
+
+        if (overlayView != null && startValues != null) {
+            // TODO: Need to do this for general case of adding to overlay
+            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
+            int screenX = screenLoc[0];
+            int screenY = screenLoc[1];
+            int[] loc = new int[2];
+            sceneRoot.getLocationOnScreen(loc);
+            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
+            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
+            final ViewGroupOverlayImpl overlay = ViewGroupUtils.getOverlay(sceneRoot);
+            overlay.add(overlayView);
+            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
+            if (animator == null) {
+                overlay.remove(overlayView);
+            } else {
+                final View finalOverlayView = overlayView;
+                animator.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        overlay.remove(finalOverlayView);
+                    }
+                });
+            }
+            return animator;
+        }
+
+        if (viewToKeep != null) {
+            int originalVisibility = -1;
+            originalVisibility = viewToKeep.getVisibility();
+            viewToKeep.setVisibility(View.VISIBLE);
+            Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
+            if (animator != null) {
+                final View finalViewToKeep = viewToKeep;
+                animator.addListener(new AnimatorListenerAdapter() {
+                    boolean mCanceled = false;
+
+                    @Override
+                    public void onAnimationPause(Animator animation) {
+                        if (!mCanceled) {
+                            //noinspection WrongConstant
+                            finalViewToKeep.setVisibility(finalVisibility);
+                        }
+                    }
+
+                    @Override
+                    public void onAnimationResume(Animator animation) {
+                        if (!mCanceled) {
+                            finalViewToKeep.setVisibility(View.VISIBLE);
+                        }
+                    }
+
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        mCanceled = true;
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        if (!mCanceled) {
+                            //noinspection WrongConstant
+                            finalViewToKeep.setVisibility(finalVisibility);
+                        }
+                    }
+                });
+            } else {
+                viewToKeep.setVisibility(originalVisibility);
+            }
+            return animator;
+        }
+        return null;
+
+
+    }
+
+    /**
+     * The default implementation of this method returns a null Animator. Subclasses should
+     * override this method to make targets disappear with the desired transition. The
+     * method should only be called from
+     * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+     *
+     * @param sceneRoot   The root of the transition hierarchy
+     * @param view        The View to make disappear. This will be in the target scene's View
+     *                    hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
+     *                    VISIBLE.
+     * @param startValues The target values in the start scene
+     * @param endValues   The target values in the end scene
+     * @return An Animator to be started at the appropriate time in the
+     * overall transition for this scene change. A null value means no animation
+     * should be run.
+     */
+    public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+            TransitionValues endValues) {
         return null;
     }
 
@@ -236,7 +490,6 @@
                 || changeInfo.mEndVisibility == View.VISIBLE);
     }
 
-    // TODO: Implement API 21; onAppear (4 params), onDisappear (4 params), getMode, setMode
     // TODO: Implement API 23; isTransitionRequired
 
 }
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/auto_transition.xml
similarity index 70%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/auto_transition.xml
index 36c297f..ae9ed46 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/auto_transition.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -14,9 +14,4 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<autoTransition/>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/custom_transition.xml
similarity index 64%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/custom_transition.xml
index 36c297f..1d17d44 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/custom_transition.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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
+         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,
@@ -14,9 +14,4 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<transition class="android.support.transition.TransitionInflaterTest$CustomTransition"/>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/fade.xml
similarity index 70%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/fade.xml
index 36c297f..b36fa2b 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/fade.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -14,9 +14,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<fade xmlns:android="http://schemas.android.com/apk/res/android"
+      android:fadingMode="fade_out"/>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/target_classes.xml
similarity index 60%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/target_classes.xml
index 36c297f..adfaee1 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/target_classes.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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
+         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,
@@ -14,9 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetClass="android.widget.TextView"/>
+        <target android:targetClass="android.widget.ImageView"/>
+    </targets>
+</changeBounds>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/target_ids.xml
similarity index 63%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/target_ids.xml
index 36c297f..eb17888 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/target_ids.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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
+         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,
@@ -14,9 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetId="@+id/hello"/>
+        <target android:targetId="@+id/world"/>
+    </targets>
+</changeBounds>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/target_names.xml
similarity index 63%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/target_names.xml
index 36c297f..6485198 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/target_names.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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
+         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,
@@ -14,9 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetName="hello"/>
+        <target android:targetName="world"/>
+    </targets>
+</changeBounds>
diff --git a/transition/tests/res/transition/transition_constructors.xml b/transition/tests/res/transition/transition_constructors.xml
new file mode 100644
index 0000000..c820959
--- /dev/null
+++ b/transition/tests/res/transition/transition_constructors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 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.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+    <transition class="android.support.transition.TransitionInflaterTest$InflationFade"/>
+    <transition class="android.support.transition.TransitionInflaterTest$InflationChangeBounds"/>
+    <transition class="android.support.transition.TransitionInflaterTest$InflationAutoTransition"/>
+    <transition class="android.support.transition.TransitionInflaterTest$InflationTransitionSet"/>
+</transitionSet>
diff --git a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml b/transition/tests/res/transition/transition_set.xml
similarity index 70%
copy from samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
copy to transition/tests/res/transition/transition_set.xml
index 36c297f..045860a 100644
--- a/samples/SupportVectorDrawable/animated/res/anim/animation_grouping_1_01.xml
+++ b/transition/tests/res/transition/transition_set.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -14,9 +14,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="3300"
-    android:propertyName="rotation"
-    android:valueFrom="0"
-    android:valueTo="450" />
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+               android:transitionOrdering="sequential">
+    <changeBounds/>
+    <fade/>
+</transitionSet>
diff --git a/transition/tests/src/android/support/transition/ArcMotionTest.java b/transition/tests/src/android/support/transition/ArcMotionTest.java
new file mode 100644
index 0000000..75d6117
--- /dev/null
+++ b/transition/tests/src/android/support/transition/ArcMotionTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Path;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ArcMotionTest extends PathMotionTest {
+
+    @Test
+    public void test90Quadrants() {
+        ArcMotion arcMotion = new ArcMotion();
+        arcMotion.setMaximumAngle(90);
+
+        Path expected = arcWithPoint(0, 100, 100, 0, 100, 100);
+        Path path = arcMotion.getPath(0, 100, 100, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(100, 0, 0, -100, 0, 0);
+        path = arcMotion.getPath(100, 0, 0, -100);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(0, -100, -100, 0, 0, 0);
+        path = arcMotion.getPath(0, -100, -100, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(-100, 0, 0, 100, -100, 100);
+        path = arcMotion.getPath(-100, 0, 0, 100);
+        assertPathMatches(expected, path);
+    }
+
+    @Test
+    public void test345Triangles() {
+        // 3-4-5 triangles are easy to calculate the control points
+        ArcMotion arcMotion = new ArcMotion();
+        arcMotion.setMaximumAngle(90);
+        Path expected;
+        Path path;
+
+        expected = arcWithPoint(0, 120, 160, 0, 125, 120);
+        path = arcMotion.getPath(0, 120, 160, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(0, 160, 120, 0, 120, 125);
+        path = arcMotion.getPath(0, 160, 120, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(-120, 0, 0, 160, -120, 125);
+        path = arcMotion.getPath(-120, 0, 0, 160);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(-160, 0, 0, 120, -125, 120);
+        path = arcMotion.getPath(-160, 0, 0, 120);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(0, -120, -160, 0, -35, 0);
+        path = arcMotion.getPath(0, -120, -160, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(0, -160, -120, 0, 0, -35);
+        path = arcMotion.getPath(0, -160, -120, 0);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(120, 0, 0, -160, 0, -35);
+        path = arcMotion.getPath(120, 0, 0, -160);
+        assertPathMatches(expected, path);
+
+        expected = arcWithPoint(160, 0, 0, -120, 35, 0);
+        path = arcMotion.getPath(160, 0, 0, -120);
+        assertPathMatches(expected, path);
+    }
+
+    private static Path arcWithPoint(float startX, float startY, float endX, float endY,
+            float eX, float eY) {
+        float c1x = (eX + startX) / 2;
+        float c1y = (eY + startY) / 2;
+        float c2x = (eX + endX) / 2;
+        float c2y = (eY + endY) / 2;
+        Path path = new Path();
+        path.moveTo(startX, startY);
+        path.cubicTo(c1x, c1y, c2x, c2y, endX, endY);
+        return path;
+    }
+
+    @Test
+    public void testMaximumAngle() {
+        ArcMotion arcMotion = new ArcMotion();
+        arcMotion.setMaximumAngle(45f);
+        assertEquals(45f, arcMotion.getMaximumAngle(), 0.0f);
+
+        float ratio = (float) Math.tan(Math.PI / 8);
+        float ex = 50 + (50 * ratio);
+        float ey = ex;
+
+        Path expected = arcWithPoint(0, 100, 100, 0, ex, ey);
+        Path path = arcMotion.getPath(0, 100, 100, 0);
+        assertPathMatches(expected, path);
+    }
+
+    @Test
+    public void testMinimumHorizontalAngle() {
+        ArcMotion arcMotion = new ArcMotion();
+        arcMotion.setMinimumHorizontalAngle(45);
+        assertEquals(45, arcMotion.getMinimumHorizontalAngle(), 0.0f);
+
+        float ex = 37.5f;
+        float ey = (float) (Math.tan(Math.PI / 4) * 50);
+        Path expected = arcWithPoint(0, 0, 100, 50, ex, ey);
+        Path path = arcMotion.getPath(0, 0, 100, 50);
+        assertPathMatches(expected, path);
+
+        // Pretty much the same, but follows a different path.
+        expected = arcWithPoint(0, 0, 100.001f, 50, ex, ey);
+        path = arcMotion.getPath(0, 0, 100.001f, 50);
+        assertPathMatches(expected, path);
+
+        // Moving in the opposite direction.
+        expected = arcWithPoint(100, 50, 0, 0, ex, ey);
+        path = arcMotion.getPath(100, 50, 0, 0);
+        assertPathMatches(expected, path);
+
+        // With x < y.
+        ex = 0;
+        ey = (float) (Math.tan(Math.PI / 4) * 62.5f);
+        expected = arcWithPoint(0, 0, 50, 100, ex, ey);
+        path = arcMotion.getPath(0, 0, 50, 100);
+        assertPathMatches(expected, path);
+
+        // Pretty much the same, but follows a different path.
+        expected = arcWithPoint(0, 0, 50, 100.001f, ex, ey);
+        path = arcMotion.getPath(0, 0, 50, 100.001f);
+        assertPathMatches(expected, path);
+
+        // Moving in the opposite direction.
+        expected = arcWithPoint(50, 100, 0, 0, ex, ey);
+        path = arcMotion.getPath(50, 100, 0, 0);
+        assertPathMatches(expected, path);
+    }
+
+    @Test
+    public void testMinimumVerticalAngle() {
+        ArcMotion arcMotion = new ArcMotion();
+        arcMotion.setMinimumVerticalAngle(45);
+        assertEquals(45, arcMotion.getMinimumVerticalAngle(), 0.0f);
+
+        float ex = 0;
+        float ey = 62.5f;
+        Path expected = arcWithPoint(0, 0, 50, 100, ex, ey);
+        Path path = arcMotion.getPath(0, 0, 50, 100);
+        assertPathMatches(expected, path);
+
+        // Pretty much the same, but follows a different path.
+        expected = arcWithPoint(0, 0, 50, 100.001f, ex, ey);
+        path = arcMotion.getPath(0, 0, 50, 100.001f);
+        assertPathMatches(expected, path);
+
+        // Moving in opposite direction.
+        expected = arcWithPoint(50, 100, 0, 0, ex, ey);
+        path = arcMotion.getPath(50, 100, 0, 0);
+        assertPathMatches(expected, path);
+
+        // With x > y.
+        ex = (float) (Math.tan(Math.PI / 4) * 37.5f);
+        ey = 50;
+        expected = arcWithPoint(0, 0, 100, 50, ex, ey);
+        path = arcMotion.getPath(0, 0, 100, 50);
+        assertPathMatches(expected, path);
+
+        // Pretty much the same, but follows a different path.
+        expected = arcWithPoint(0, 0, 100.001f, 50, ex, ey);
+        path = arcMotion.getPath(0, 0, 100.001f, 50);
+        assertPathMatches(expected, path);
+
+        // Moving in opposite direction.
+        expected = arcWithPoint(100, 50, 0, 0, ex, ey);
+        path = arcMotion.getPath(100, 50, 0, 0);
+        assertPathMatches(expected, path);
+
+    }
+
+}
diff --git a/transition/tests/src/android/support/transition/FadeTest.java b/transition/tests/src/android/support/transition/FadeTest.java
index ba6440c..0493a99 100644
--- a/transition/tests/src/android/support/transition/FadeTest.java
+++ b/transition/tests/src/android/support/transition/FadeTest.java
@@ -45,6 +45,16 @@
     }
 
     @Test
+    public void testMode() {
+        assertThat(Fade.IN, is(Visibility.MODE_IN));
+        assertThat(Fade.OUT, is(Visibility.MODE_OUT));
+        final Fade fade = new Fade();
+        assertThat(fade.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT));
+        fade.setMode(Visibility.MODE_IN);
+        assertThat(fade.getMode(), is(Visibility.MODE_IN));
+    }
+
+    @Test
     @UiThreadTest
     public void testDisappear() {
         final Fade fade = new Fade();
diff --git a/transition/tests/src/android/support/transition/PathMotionTest.java b/transition/tests/src/android/support/transition/PathMotionTest.java
new file mode 100644
index 0000000..7be63c0
--- /dev/null
+++ b/transition/tests/src/android/support/transition/PathMotionTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+
+public abstract class PathMotionTest {
+
+    public static void assertPathMatches(Path expectedPath, Path path) {
+        PathMeasure expectedMeasure = new PathMeasure(expectedPath, false);
+        PathMeasure pathMeasure = new PathMeasure(path, false);
+
+        float expectedLength = expectedMeasure.getLength();
+        assertEquals("Lengths differ", expectedLength, pathMeasure.getLength(), 0.01f);
+
+        float minLength = Math.min(expectedLength, pathMeasure.getLength());
+
+        float[] pos = new float[2];
+
+        float increment = minLength / 5f;
+        for (float along = 0; along <= minLength; along += increment) {
+            expectedMeasure.getPosTan(along, pos, null);
+            float expectedX = pos[0];
+            float expectedY = pos[1];
+
+            pathMeasure.getPosTan(along, pos, null);
+            assertEquals("Failed at " + increment, expectedX, pos[0], 0.01f);
+            assertEquals("Failed at " + increment, expectedY, pos[1], 0.01f);
+        }
+    }
+
+}
diff --git a/transition/tests/src/android/support/transition/PatternPathMotionTest.java b/transition/tests/src/android/support/transition/PatternPathMotionTest.java
new file mode 100644
index 0000000..b14ceaa
--- /dev/null
+++ b/transition/tests/src/android/support/transition/PatternPathMotionTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import static org.junit.Assert.assertSame;
+
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PatternPathMotionTest extends PathMotionTest {
+
+    @Test
+    public void testStraightPath() {
+        Path pattern = new Path();
+        pattern.moveTo(100, 500);
+        pattern.lineTo(300, 1000);
+
+        PatternPathMotion pathMotion = new PatternPathMotion(pattern);
+        assertPathMatches(pattern, pathMotion.getPatternPath());
+
+        Path expected = new Path();
+        expected.moveTo(0, 0);
+        expected.lineTo(100, 100);
+
+        assertPathMatches(expected, pathMotion.getPath(0, 0, 100, 100));
+    }
+
+    @Test
+    public void testCurve() {
+        RectF oval = new RectF();
+        Path pattern = new Path();
+        oval.set(0, 0, 100, 100);
+        pattern.addArc(oval, 0, 180);
+
+        PatternPathMotion pathMotion = new PatternPathMotion(pattern);
+        assertPathMatches(pattern, pathMotion.getPatternPath());
+
+        Path expected = new Path();
+        oval.set(-50, 0, 50, 100);
+        expected.addArc(oval, -90, 180);
+
+        assertPathMatches(expected, pathMotion.getPath(0, 0, 0, 100));
+    }
+
+    @Test
+    public void testSetPatternPath() {
+        Path pattern = new Path();
+        RectF oval = new RectF(0, 0, 100, 100);
+        pattern.addArc(oval, 0, 180);
+
+        PatternPathMotion patternPathMotion = new PatternPathMotion();
+        patternPathMotion.setPatternPath(pattern);
+        assertSame(pattern, patternPathMotion.getPatternPath());
+    }
+
+}
diff --git a/transition/tests/src/android/support/transition/TransitionInflaterTest.java b/transition/tests/src/android/support/transition/TransitionInflaterTest.java
new file mode 100644
index 0000000..28c97d8
--- /dev/null
+++ b/transition/tests/src/android/support/transition/TransitionInflaterTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 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.transition;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.test.filters.MediumTest;
+import android.support.transition.test.R;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.junit.Test;
+
+import java.util.List;
+
+@MediumTest
+public class TransitionInflaterTest extends BaseTest {
+
+    @Test
+    public void testInflationConstructors() throws Throwable {
+        TransitionInflater inflater = TransitionInflater.from(rule.getActivity());
+        // TODO: Add more Transition types
+        Transition transition = inflater.inflateTransition(R.transition.transition_constructors);
+        assertTrue(transition instanceof TransitionSet);
+        TransitionSet set = (TransitionSet) transition;
+        assertEquals(4, set.getTransitionCount());
+    }
+
+    @Test
+    public void testInflation() {
+        TransitionInflater inflater = TransitionInflater.from(rule.getActivity());
+        // TODO: Add more Transition types
+        verifyFadeProperties(inflater.inflateTransition(R.transition.fade));
+        verifyAutoTransitionProperties(inflater.inflateTransition(R.transition.auto_transition));
+        verifyTransitionSetProperties(inflater.inflateTransition(R.transition.transition_set));
+        verifyCustomTransitionProperties(
+                inflater.inflateTransition(R.transition.custom_transition));
+        verifyTargetIds(inflater.inflateTransition(R.transition.target_ids));
+        verifyTargetNames(inflater.inflateTransition(R.transition.target_names));
+        verifyTargetClass(inflater.inflateTransition(R.transition.target_classes));
+    }
+
+    // TODO: Add test for TransitionManager
+
+    private void verifyFadeProperties(Transition transition) {
+        assertTrue(transition instanceof Fade);
+        Fade fade = (Fade) transition;
+        assertEquals(Fade.OUT, fade.getMode());
+    }
+
+    private void verifyAutoTransitionProperties(Transition transition) {
+        assertTrue(transition instanceof AutoTransition);
+    }
+
+    private void verifyTransitionSetProperties(Transition transition) {
+        assertTrue(transition instanceof TransitionSet);
+        TransitionSet set = (TransitionSet) transition;
+        assertEquals(TransitionSet.ORDERING_SEQUENTIAL, set.getOrdering());
+        assertEquals(2, set.getTransitionCount());
+        assertTrue(set.getTransitionAt(0) instanceof ChangeBounds);
+        assertTrue(set.getTransitionAt(1) instanceof Fade);
+    }
+
+    private void verifyCustomTransitionProperties(Transition transition) {
+        assertTrue(transition instanceof CustomTransition);
+    }
+
+    private void verifyTargetIds(Transition transition) {
+        List<Integer> targets = transition.getTargetIds();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals(R.id.hello, (int) targets.get(0));
+        assertEquals(R.id.world, (int) targets.get(1));
+    }
+
+    private void verifyTargetNames(Transition transition) {
+        List<String> targets = transition.getTargetNames();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals("hello", targets.get(0));
+        assertEquals("world", targets.get(1));
+    }
+
+    private void verifyTargetClass(Transition transition) {
+        List<Class> targets = transition.getTargetTypes();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals(TextView.class, targets.get(0));
+        assertEquals(ImageView.class, targets.get(1));
+    }
+
+    public static class CustomTransition extends Transition {
+        public CustomTransition() {
+            fail("Default constructor was not expected");
+        }
+
+        @SuppressWarnings("unused") // This constructor is used in XML
+        public CustomTransition(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        @Override
+        public void captureStartValues(@NonNull TransitionValues transitionValues) {
+        }
+
+        @Override
+        public void captureEndValues(@NonNull TransitionValues transitionValues) {
+        }
+    }
+
+    public static class InflationFade extends Fade {
+        public InflationFade(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeBounds extends ChangeBounds {
+        public InflationChangeBounds(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationTransitionSet extends TransitionSet {
+        public InflationTransitionSet(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationAutoTransition extends AutoTransition {
+        public InflationAutoTransition(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+}
diff --git a/transition/tests/src/android/support/transition/TransitionTest.java b/transition/tests/src/android/support/transition/TransitionTest.java
index 03623b5..f9370c9 100644
--- a/transition/tests/src/android/support/transition/TransitionTest.java
+++ b/transition/tests/src/android/support/transition/TransitionTest.java
@@ -314,12 +314,15 @@
 
     public static class EmptyTransition extends Transition {
 
+        @Override
         public void captureEndValues(@NonNull TransitionValues transitionValues) {
         }
 
+        @Override
         public void captureStartValues(@NonNull TransitionValues transitionValues) {
         }
 
+        @Override
         public Animator createAnimator(@NonNull ViewGroup sceneRoot,
                 @Nullable TransitionValues startValues,
                 @Nullable TransitionValues endValues) {
@@ -330,18 +333,23 @@
 
     public static class EmptyTransitionListener implements Transition.TransitionListener {
 
+        @Override
         public void onTransitionStart(@NonNull Transition transition) {
         }
 
+        @Override
         public void onTransitionEnd(@NonNull Transition transition) {
         }
 
+        @Override
         public void onTransitionCancel(@NonNull Transition transition) {
         }
 
+        @Override
         public void onTransitionPause(@NonNull Transition transition) {
         }
 
+        @Override
         public void onTransitionResume(@NonNull Transition transition) {
         }
 
diff --git a/transition/tests/src/android/support/transition/VisibilityTest.java b/transition/tests/src/android/support/transition/VisibilityTest.java
index 4897a85..dcfcbdc 100644
--- a/transition/tests/src/android/support/transition/VisibilityTest.java
+++ b/transition/tests/src/android/support/transition/VisibilityTest.java
@@ -50,6 +50,14 @@
     }
 
     @Test
+    public void testMode() {
+        final CustomVisibility visibility = new CustomVisibility();
+        assertThat(visibility.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT));
+        visibility.setMode(Visibility.MODE_IN);
+        assertThat(visibility.getMode(), is(Visibility.MODE_IN));
+    }
+
+    @Test
     @UiThreadTest
     public void testCustomVisibility() {
         final CustomVisibility visibility = new CustomVisibility();
@@ -82,6 +90,31 @@
         assertThat((float) animator.getAnimatedValue(), is(0.25f));
     }
 
+    @Test
+    @UiThreadTest
+    public void testCustomVisibility2() {
+        final CustomVisibility2 visibility = new CustomVisibility2();
+        final TransitionValues startValues = new TransitionValues();
+        startValues.view = mView;
+        visibility.captureStartValues(startValues);
+        mView.setVisibility(View.GONE);
+        final TransitionValues endValues = new TransitionValues();
+        endValues.view = mView;
+        visibility.captureEndValues(endValues);
+        ObjectAnimator animator = (ObjectAnimator) visibility
+                .createAnimator(mRoot, startValues, endValues);
+        assertNotNull(animator);
+
+        // Jump to the end of the animation
+        animator.end();
+
+        // This value confirms that onDisappear, not onAppear, was called
+        assertThat((float) animator.getAnimatedValue(), is(0.25f));
+    }
+
+    /**
+     * A custom {@link Visibility} with 5-arg onAppear/Disappear
+     */
     public static class CustomVisibility extends Visibility {
 
         static final String PROPNAME_SCALE_X = "customVisibility:scaleX";
@@ -131,4 +164,37 @@
 
     }
 
+    /**
+     * A custom {@link Visibility} with 4-arg onAppear/Disappear
+     */
+    public static class CustomVisibility2 extends Visibility {
+
+        static final String PROPNAME_SCALE_X = "customVisibility:scaleX";
+
+        @Override
+        public void captureStartValues(@NonNull TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            transitionValues.values.put(PROPNAME_SCALE_X, transitionValues.view.getScaleX());
+        }
+
+        @Override
+        public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+                TransitionValues endValues) {
+            float startScaleX = startValues == null ? 0.25f :
+                    (float) startValues.values.get(PROPNAME_SCALE_X);
+            return ObjectAnimator.ofFloat(view, "scaleX", startScaleX, 0.75f);
+        }
+
+        @Override
+        public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+                TransitionValues endValues) {
+            if (startValues == null) {
+                return null;
+            }
+            float startScaleX = (float) startValues.values.get(PROPNAME_SCALE_X);
+            return ObjectAnimator.ofFloat(view, "scaleX", startScaleX, 0.25f);
+        }
+
+    }
+
 }
diff --git a/v13/java/android/support/v13/view/inputmethod/EditorInfoCompat.java b/v13/java/android/support/v13/view/inputmethod/EditorInfoCompat.java
index 4a6d3a0..92743c2 100644
--- a/v13/java/android/support/v13/view/inputmethod/EditorInfoCompat.java
+++ b/v13/java/android/support/v13/view/inputmethod/EditorInfoCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v13.view.inputmethod;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
@@ -102,7 +102,7 @@
         }
     }
 
-    @TargetApi(25)
+    @RequiresApi(25)
     private static final class EditorInfoCompatApi25Impl implements EditorInfoCompatImpl {
         @Override
         public void setContentMimeTypes(@NonNull EditorInfo editorInfo,
diff --git a/v13/java/android/support/v13/view/inputmethod/InputConnectionCompat.java b/v13/java/android/support/v13/view/inputmethod/InputConnectionCompat.java
index ba16fd0..5999575 100644
--- a/v13/java/android/support/v13/view/inputmethod/InputConnectionCompat.java
+++ b/v13/java/android/support/v13/view/inputmethod/InputConnectionCompat.java
@@ -16,7 +16,7 @@
 
 package android.support.v13.view.inputmethod;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.ClipDescription;
 import android.net.Uri;
 import android.os.Build;
@@ -130,7 +130,7 @@
         }
     }
 
-    @TargetApi(25)
+    @RequiresApi(25)
     private static final class InputContentInfoCompatApi25Impl
             implements InputConnectionCompatImpl {
         @Override
diff --git a/v13/tests/java/android/support/v13/view/DragStartHelperTest.java b/v13/tests/java/android/support/v13/view/DragStartHelperTest.java
index 21cd71e..c92de6a 100644
--- a/v13/tests/java/android/support/v13/view/DragStartHelperTest.java
+++ b/v13/tests/java/android/support/v13/view/DragStartHelperTest.java
@@ -147,10 +147,12 @@
             this(anchor.getWidth() / 2 + x, anchor.getHeight() / 2 + y);
         }
 
+        @Override
         public boolean matches(Object actual) {
             return mExpectedPosition.equals(actual);
         }
 
+        @Override
         public void describeTo(Description description) {
             description.appendText("TouchPositionMatcher: " + mExpectedPosition);
         }
diff --git a/v14/preference/res/layout/preference_widget_seekbar_material.xml b/v14/preference/res/layout/preference_widget_seekbar_material.xml
index f54108a..2a6fd98 100644
--- a/v14/preference/res/layout/preference_widget_seekbar_material.xml
+++ b/v14/preference/res/layout/preference_widget_seekbar_material.xml
@@ -25,7 +25,7 @@
               android:clipToPadding="false">
 
     <ImageView
-            android:id="@+android:id/icon"
+            android:id="@android:id/icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
@@ -42,7 +42,7 @@
             android:clipChildren="false"
             android:clipToPadding="false">
 
-        <TextView android:id="@+android:id/title"
+        <TextView android:id="@android:id/title"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
@@ -50,7 +50,7 @@
                   android:ellipsize="marquee"
                   android:fadingEdge="horizontal"/>
 
-        <TextView android:id="@+android:id/summary"
+        <TextView android:id="@android:id/summary"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_below="@android:id/title"
@@ -94,4 +94,4 @@
 
     </RelativeLayout>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java
index 6b385d8..6119071 100644
--- a/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java
+++ b/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java
@@ -80,6 +80,7 @@
 
         builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
                 new DialogInterface.OnClickListener() {
+                    @Override
                     public void onClick(DialogInterface dialog, int which) {
                         mClickedDialogEntryIndex = which;
 
diff --git a/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java b/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java
index cb38c44..901bf06 100644
--- a/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java
+++ b/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java
@@ -169,6 +169,7 @@
      *
      * @return The list as an array.
      */
+    @Override
     public CharSequence[] getEntries() {
         return mEntries;
     }
@@ -197,6 +198,7 @@
      *
      * @return The array of values.
      */
+    @Override
     public CharSequence[] getEntryValues() {
         return mEntryValues;
     }
@@ -207,6 +209,7 @@
      *
      * @param values The values to set for the key.
      */
+    @Override
     public void setValues(Set<String> values) {
         mValues.clear();
         mValues.addAll(values);
@@ -217,6 +220,7 @@
     /**
      * Retrieves the current value of the key.
      */
+    @Override
     public Set<String> getValues() {
         return mValues;
     }
@@ -320,10 +324,12 @@
 
         public static final Parcelable.Creator<SavedState> CREATOR =
                 new Parcelable.Creator<SavedState>() {
+                    @Override
                     public SavedState createFromParcel(Parcel in) {
                         return new SavedState(in);
                     }
 
+                    @Override
                     public SavedState[] newArray(int size) {
                         return new SavedState[size];
                     }
diff --git a/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java
index 6f116db..8192583 100644
--- a/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java
+++ b/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java
@@ -102,6 +102,7 @@
         }
         builder.setMultiChoiceItems(mEntries, checkedItems,
                 new DialogInterface.OnMultiChoiceClickListener() {
+                    @Override
                     public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                         if (isChecked) {
                             mPreferenceChanged |= mNewValues.add(
diff --git a/v14/preference/src/android/support/v14/preference/PreferenceFragment.java b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
index 59d1d4e..433fbda 100644
--- a/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
+++ b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
@@ -157,6 +157,7 @@
     };
 
     final private Runnable mRequestFocus = new Runnable() {
+        @Override
         public void run() {
             mList.focusableViewAvailable(mList);
         }
@@ -474,6 +475,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (preference.getFragment() != null) {
             boolean handled = false;
@@ -520,6 +522,7 @@
      * @return The {@link Preference} with the key, or null.
      * @see android.support.v7.preference.PreferenceGroup#findPreference(CharSequence)
      */
+    @Override
     public Preference findPreference(CharSequence key) {
         if (mPreferenceManager == null) {
             return null;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
index 1989791..3dbc78a 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
@@ -200,6 +200,7 @@
             invalidateSelf();
         }
 
+        @Override
         public ColorFilter getColorFilter() {
             return mState.mPaint.getColorFilter();
         }
@@ -269,6 +270,7 @@
         }
 
         // Queried by system transitions
+        @Override
         public int getAlpha() {
             return mAlpha;
         }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/FragmentUtil.java b/v17/leanback/src/android/support/v17/leanback/app/FragmentUtil.java
index 23c6039..b555698 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/FragmentUtil.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/FragmentUtil.java
@@ -15,14 +15,14 @@
  */
 package android.support.v17.leanback.app;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.app.Fragment;
 import android.content.Context;
 import android.os.Build;
 
 class FragmentUtil {
 
-    @TargetApi(23)
+    @RequiresApi(23)
     private static Context getContextNew(Fragment fragment) {
         return fragment.getContext();
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
index eb2ce28..d74fd11 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
@@ -250,6 +250,7 @@
         return getControlsRowPresenter();
     }
 
+    @Override
     protected SparseArrayObjectAdapter createPrimaryActionsAdapter(
             PresenterSelector presenterSelector) {
         return super.createPrimaryActionsAdapter(presenterSelector);
diff --git a/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java b/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
index d65937c..acf4745 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/SearchFragment.java
@@ -237,6 +237,7 @@
         }
     };
 
+    @Override
     public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                            int[] grantResults) {
         if (requestCode == AUDIO_PERMISSION_REQUEST_CODE && permissions.length > 0) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
index ae4c700..36b560d 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/SearchSupportFragment.java
@@ -240,6 +240,7 @@
         }
     };
 
+    @Override
     public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                            int[] grantResults) {
         if (requestCode == AUDIO_PERMISSION_REQUEST_CODE && permissions.length > 0) {
diff --git a/v17/leanback/src/android/support/v17/leanback/graphics/CompositeDrawable.java b/v17/leanback/src/android/support/v17/leanback/graphics/CompositeDrawable.java
index 5e7e654..edbca3c 100644
--- a/v17/leanback/src/android/support/v17/leanback/graphics/CompositeDrawable.java
+++ b/v17/leanback/src/android/support/v17/leanback/graphics/CompositeDrawable.java
@@ -189,6 +189,7 @@
     /**
      * @return Alpha value between 0(inclusive) and 255(inclusive)
      */
+    @Override
     public int getAlpha() {
         final Drawable dr = getFirstNonNullDrawable();
         if (dr != null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/graphics/FitWidthBitmapDrawable.java b/v17/leanback/src/android/support/v17/leanback/graphics/FitWidthBitmapDrawable.java
index 910f313..6300ff2 100644
--- a/v17/leanback/src/android/support/v17/leanback/graphics/FitWidthBitmapDrawable.java
+++ b/v17/leanback/src/android/support/v17/leanback/graphics/FitWidthBitmapDrawable.java
@@ -15,7 +15,7 @@
  */
 package android.support.v17.leanback.graphics;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -176,6 +176,7 @@
     /**
      * @return Alpha value between 0(inclusive) and 255(inclusive)
      */
+    @Override
     public int getAlpha() {
         return mBitmapState.mPaint.getAlpha();
     }
@@ -214,10 +215,12 @@
             // use Property
             PROPERTY_VERTICAL_OFFSET = new Property<FitWidthBitmapDrawable, Integer>(Integer.class,
                     "verticalOffset") {
+                @Override
                 public void set(FitWidthBitmapDrawable object, Integer value) {
                     object.setVerticalOffset(value);
                 }
 
+                @Override
                 public Integer get(FitWidthBitmapDrawable object) {
                     return object.getVerticalOffset();
                 }
@@ -225,9 +228,10 @@
         }
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     static IntProperty<FitWidthBitmapDrawable> getVerticalOffsetIntProperty() {
         return new IntProperty<FitWidthBitmapDrawable>("verticalOffset") {
+            @Override
             public void setValue(FitWidthBitmapDrawable fitWidthBitmapDrawable, int value) {
                 fitWidthBitmapDrawable.setVerticalOffset(value);
             }
diff --git a/v17/leanback/src/android/support/v17/leanback/media/MediaPlayerGlue.java b/v17/leanback/src/android/support/v17/leanback/media/MediaPlayerGlue.java
index b0f0b8a..dd0127c 100644
--- a/v17/leanback/src/android/support/v17/leanback/media/MediaPlayerGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/media/MediaPlayerGlue.java
@@ -140,6 +140,7 @@
     /**
      * Sets the callback, which would tell the listener that video is ready to be played.
      */
+    @Override
     public void setPlayerCallback(PlayerCallback callback) {
         this.mPlayerCallback = callback;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java b/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
index b19458b..08c4b88 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BaseGridView.java
@@ -197,7 +197,7 @@
     /**
      * Number of items to prefetch when first coming on screen with new data.
      */
-    int mInitialItemPrefetchCount = 4;
+    int mInitialPrefetchItemCount = 4;
 
     public BaseGridView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
@@ -1063,12 +1063,12 @@
      *
      * @param itemCount Number of items to prefetch
      *
-     * @see #getInitialItemPrefetchCount()
+     * @see #getInitialPrefetchItemCount()
      * @see RecyclerView.LayoutManager#isItemPrefetchEnabled()
      * @see RecyclerView.LayoutManager#collectInitialPrefetchPositions(int, RecyclerView.LayoutManager.LayoutPrefetchRegistry)
      */
     public void setInitialPrefetchItemCount(int itemCount) {
-        mInitialItemPrefetchCount = itemCount;
+        mInitialPrefetchItemCount = itemCount;
     }
 
     /**
@@ -1083,7 +1083,7 @@
      *
      * @return number of items to prefetch.
      */
-    public int getInitialItemPrefetchCount() {
-        return mInitialItemPrefetchCount;
+    public int getInitialPrefetchItemCount() {
+        return mInitialPrefetchItemCount;
     }
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index fc7c890..ff0f93a 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -209,6 +209,10 @@
                 super.onStop();
                 return;
             }
+            if (mFocusPosition != getTargetPosition()) {
+                // This should not happen since we cropped value in startPositionSmoothScroller()
+                mFocusPosition = getTargetPosition();
+            }
             if (hasFocus()) {
                 mInSelection = true;
                 targetView.requestFocus();
@@ -2240,7 +2244,7 @@
     @Override
     public void collectInitialPrefetchPositions(int adapterItemCount,
             LayoutPrefetchRegistry layoutPrefetchRegistry) {
-        int numToPrefetch = mBaseGridView.mInitialItemPrefetchCount;
+        int numToPrefetch = mBaseGridView.mInitialPrefetchItemCount;
         if (adapterItemCount != 0 && numToPrefetch != 0) {
             // prefetch items centered around mFocusPosition
             int initialPos = Math.max(0, Math.min(mFocusPosition - (numToPrefetch - 1)/ 2,
@@ -2442,7 +2446,12 @@
                             + "not be called before first layout pass");
                     return;
                 }
-                startPositionSmoothScroller(position);
+                position = startPositionSmoothScroller(position);
+                if (position != mFocusPosition) {
+                    // gets cropped by adapter size
+                    mFocusPosition = position;
+                    mSubFocusPosition = 0;
+                }
             } else {
                 mForceFullLayout = true;
                 requestLayout();
@@ -2451,7 +2460,7 @@
         if (TRACE) TraceCompat.endSection();
     }
 
-    void startPositionSmoothScroller(int position) {
+    int startPositionSmoothScroller(int position) {
         LinearSmoothScroller linearSmoothScroller = new GridLinearSmoothScroller() {
             @Override
             public PointF computeScrollVectorForPosition(int targetPosition) {
@@ -2474,6 +2483,7 @@
         };
         linearSmoothScroller.setTargetPosition(position);
         startSmoothScroll(linearSmoothScroller);
+        return linearSmoothScroller.getTargetPosition();
     }
 
     private void processPendingMovement(boolean forward) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java b/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
index a8ea24c..a329c08 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
@@ -72,6 +72,7 @@
         mHeaderDock.setVisibility(show ? View.VISIBLE : View.GONE);
     }
 
+    @Override
     public void setForeground(Drawable d) {
         mForeground = d;
         setWillNotDraw(mForeground == null);
@@ -87,6 +88,7 @@
         }
     }
 
+    @Override
     public Drawable getForeground() {
         return mForeground;
     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
index 0008f93..65e4b89 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseFragmentTest.java
@@ -56,6 +56,7 @@
     @After
     public void afterTest() throws Throwable {
         activityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 if (mActivity != null) {
                     mActivity.finish();
@@ -185,6 +186,7 @@
             this.expectedRow = expectedRow;
         }
 
+        @Override
         public void run(Presenter.ViewHolder holder) {
             android.util.Log.d(TAG, dumpRecyclerView(activity.getBrowseTestFragment()
                     .getGridView()));
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
index c7862c9..9778e4f 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/BrowseSupportFragmentTest.java
@@ -59,6 +59,7 @@
     @After
     public void afterTest() throws Throwable {
         activityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 if (mActivity != null) {
                     mActivity.finish();
@@ -188,6 +189,7 @@
             this.expectedRow = expectedRow;
         }
 
+        @Override
         public void run(Presenter.ViewHolder holder) {
             android.util.Log.d(TAG, dumpRecyclerView(activity.getBrowseTestSupportFragment()
                     .getGridView()));
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestFragment.java b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestFragment.java
index ef6a1a3..354e574 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestFragment.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestFragment.java
@@ -103,6 +103,7 @@
         mPhotoItem = photoItem;
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (getActivity() == null) {
                     return;
@@ -121,6 +122,7 @@
 
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (getActivity() == null) {
                     return;
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestSupportFragment.java b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestSupportFragment.java
index d963c3e..7d03a45 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestSupportFragment.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsTestSupportFragment.java
@@ -106,6 +106,7 @@
         mPhotoItem = photoItem;
         mRowsAdapter.clear();
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (getActivity() == null) {
                     return;
@@ -124,6 +125,7 @@
 
 
         new Handler().postDelayed(new Runnable() {
+            @Override
             public void run() {
                 if (getActivity() == null) {
                     return;
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepFragmentTest.java
index 80ca4eb..bb8e94b 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepFragmentTest.java
@@ -56,6 +56,7 @@
         final String secondFragmentName = generateMethodTestName("second");
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
@@ -63,6 +64,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
@@ -131,6 +133,7 @@
         final String secondFragmentName = generateMethodTestName("second");
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
@@ -142,6 +145,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
@@ -197,6 +201,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1001).title("Finish activity").build());
@@ -204,6 +209,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
@@ -229,6 +235,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1001).title("Finish fragments").build());
@@ -236,6 +243,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
@@ -266,6 +274,7 @@
         final boolean[] expandSubActionInOnCreateView = new boolean[] {false};
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
                         invocation.getMock();
@@ -277,6 +286,7 @@
         }).when(first).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
                 any(Bundle.class), any(View.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 List<GuidedAction> subActions = new ArrayList<GuidedAction>();
@@ -288,6 +298,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Boolean>() {
+            @Override
             public Boolean answer(InvocationOnMock invocation) {
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
                         invocation.getMock();
@@ -358,6 +369,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 List<GuidedAction> subActions = new ArrayList<GuidedAction>();
@@ -368,6 +380,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Boolean>() {
+            @Override
             public Boolean answer(InvocationOnMock invocation) {
                 GuidedStepTestFragment.Provider obj = (GuidedStepTestFragment.Provider)
                         invocation.getMock();
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepSupportFragmentTest.java
index 880236e..f2ac612 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/GuidedStepSupportFragmentTest.java
@@ -59,6 +59,7 @@
         final String secondFragmentName = generateMethodTestName("second");
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
@@ -66,6 +67,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
@@ -134,6 +136,7 @@
         final String secondFragmentName = generateMethodTestName("second");
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1000).title("OK").build());
@@ -145,6 +148,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
@@ -200,6 +204,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1001).title("Finish activity").build());
@@ -207,6 +212,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
@@ -232,6 +238,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 actions.add(new GuidedAction.Builder().id(1001).title("Finish fragments").build());
@@ -239,6 +246,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedAction action = (GuidedAction) invocation.getArguments()[0];
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
@@ -269,6 +277,7 @@
         final boolean[] expandSubActionInOnCreateView = new boolean[] {false};
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
                         invocation.getMock();
@@ -280,6 +289,7 @@
         }).when(first).onCreateView(any(LayoutInflater.class), any(ViewGroup.class),
                 any(Bundle.class), any(View.class));
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 List<GuidedAction> subActions = new ArrayList<GuidedAction>();
@@ -291,6 +301,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Boolean>() {
+            @Override
             public Boolean answer(InvocationOnMock invocation) {
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
                         invocation.getMock();
@@ -361,6 +372,7 @@
         final String firstFragmentName = generateMethodTestName("first");
         GuidedStepTestSupportFragment.Provider first = mockProvider(firstFragmentName);
         doAnswer(new Answer<Void>() {
+            @Override
             public Void answer(InvocationOnMock invocation) {
                 List actions = (List) invocation.getArguments()[0];
                 List<GuidedAction> subActions = new ArrayList<GuidedAction>();
@@ -371,6 +383,7 @@
             }
         }).when(first).onCreateActions(any(List.class), any(Bundle.class));
         doAnswer(new Answer<Boolean>() {
+            @Override
             public Boolean answer(InvocationOnMock invocation) {
                 GuidedStepTestSupportFragment.Provider obj = (GuidedStepTestSupportFragment.Provider)
                         invocation.getMock();
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackFragmentTest.java
index 7282eac..b1c6d14 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackFragmentTest.java
@@ -55,6 +55,7 @@
         final PlaybackTestFragment fragment = (PlaybackTestFragment) mActivity.getTestFragment();
         PlaybackGlue glue = fragment.getGlue();
         activityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mActivity.finish();
             }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackOverlayTestFragment.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackOverlayTestFragment.java
index e5dbe08..388cfc8 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackOverlayTestFragment.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackOverlayTestFragment.java
@@ -84,6 +84,7 @@
         }
     };
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackSupportFragmentTest.java
index e32d90b..b21ea01 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackSupportFragmentTest.java
@@ -58,6 +58,7 @@
         final PlaybackTestSupportFragment fragment = (PlaybackTestSupportFragment) mActivity.getTestFragment();
         PlaybackGlue glue = fragment.getGlue();
         activityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mActivity.finish();
             }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestFragment.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestFragment.java
index 51c2c10..99a7fc6 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestFragment.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestFragment.java
@@ -62,6 +62,7 @@
     private ListRowPresenter mListRowPresenter;
     boolean mDestroyCalled;
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestSupportFragment.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestSupportFragment.java
index 1234421..ef99eb6 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestSupportFragment.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackTestSupportFragment.java
@@ -65,6 +65,7 @@
     private ListRowPresenter mListRowPresenter;
     boolean mDestroyCalled;
 
+    @Override
     public SparseArrayObjectAdapter getAdapter() {
         return (SparseArrayObjectAdapter) super.getAdapter();
     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/RowsFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/RowsFragmentTest.java
index 193203e..80cdb8c 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/RowsFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/RowsFragmentTest.java
@@ -217,6 +217,7 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 new Runnable() {
+                    @Override
                     public void run() {
                         mActivity.recreate();
                     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/RowsSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/RowsSupportFragmentTest.java
index 70ddbac..2a00f71 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/RowsSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/RowsSupportFragmentTest.java
@@ -220,6 +220,7 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 new Runnable() {
+                    @Override
                     public void run() {
                         mActivity.recreate();
                     }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/SingleFragmentTestBase.java b/v17/leanback/tests/java/android/support/v17/leanback/app/SingleFragmentTestBase.java
index 6c1f5bc..561facb 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/SingleFragmentTestBase.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/SingleFragmentTestBase.java
@@ -42,6 +42,7 @@
         if (activity != null) {
             mActivity = null;
             activityTestRule.runOnUiThread(new Runnable() {
+                @Override
                 public void run() {
                     activity.finish();
                 }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/SingleSupportFragmentTestBase.java b/v17/leanback/tests/java/android/support/v17/leanback/app/SingleSupportFragmentTestBase.java
index 9c872f8..3083ecf 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/SingleSupportFragmentTestBase.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/SingleSupportFragmentTestBase.java
@@ -45,6 +45,7 @@
         if (activity != null) {
             mActivity = null;
             activityTestRule.runOnUiThread(new Runnable() {
+                @Override
                 public void run() {
                     activity.finish();
                 }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridFragmentTest.java
index 5c4f4fd..2a56acd 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridFragmentTest.java
@@ -50,6 +50,7 @@
         launchAndWaitActivity(GridFragment.class, 500);
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
             public void run() {
                 GridFragment f = new GridFragment();
                 mActivity.getFragmentManager().beginTransaction()
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridSupportFragmentTest.java
index 8b58c33..f6d0a1b 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/VerticalGridSupportFragmentTest.java
@@ -53,6 +53,7 @@
         launchAndWaitActivity(GridFragment.class, 500);
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
             public void run() {
                 GridFragment f = new GridFragment();
                 mActivity.getSupportFragmentManager().beginTransaction()
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetPrefetchTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetPrefetchTest.java
index 4b075ea..fcb264e 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetPrefetchTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetPrefetchTest.java
@@ -248,11 +248,11 @@
         view.setAdapter(createBoxAdapter());
 
         // check default
-        assertEquals(4, view.getInitialItemPrefetchCount());
+        assertEquals(4, view.getInitialPrefetchItemCount());
 
         // check setter behavior
         view.setInitialPrefetchItemCount(0);
-        assertEquals(0, view.getInitialItemPrefetchCount());
+        assertEquals(0, view.getInitialPrefetchItemCount());
 
         // check positions fetched, relative to focus
         view.scrollToPosition(2);
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
index 1f4bf3d..1e314e4 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -82,6 +82,7 @@
     protected int[] mRemovedItems;
 
     private final Comparator<View> mRowSortComparator = new Comparator<View>() {
+        @Override
         public int compare(View lhs, View rhs) {
             if (mOrientation == BaseGridView.HORIZONTAL) {
                 return lhs.getLeft() - rhs.getLeft();
@@ -121,6 +122,7 @@
      */
     private void changeArraySize(final int size) throws Throwable {
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mActivity.changeArraySize(size);
             }
@@ -141,6 +143,7 @@
      */
     private void setSelectedPosition(final int position, final int scrollExtra) throws Throwable {
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPosition(position, scrollExtra);
             }
@@ -356,6 +359,7 @@
         mActivityTestRule = new ActivityTestRule<GridActivity>(GridActivity.class, false, false);
         mActivity = mActivityTestRule.launchActivity(intent);
         mActivityTestRule.runOnUiThread(new Runnable() {
+                @Override
                 public void run() {
                     mActivity.setTitle(testName.getMethodName());
                 }
@@ -547,6 +551,7 @@
         final int decorationBottom = 2;
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop,
                         decorationRight, decorationBottom));
@@ -614,6 +619,7 @@
         assertTrue(opticalInsetsBottom > 0);
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mGridView.addItemDecoration(new DividerDecoration(decorationLeft, decorationTop,
                         decorationRight, decorationBottom));
@@ -841,16 +847,19 @@
         final int focusToIndex = 49;
         final ViewGroup parent = (ViewGroup) mGridView.getParent();
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 parent.removeView(mGridView);
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 parent.addView(mGridView);
                 mGridView.requestFocus();
@@ -862,16 +871,19 @@
 
         final int focusToIndex2 = 0;
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 parent.removeView(mGridView);
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPosition(focusToIndex2);
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 parent.addView(mGridView);
                 mGridView.requestFocus();
@@ -895,6 +907,7 @@
 
         final int focusToIndex = mGridView.getChildCount() - 1;
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
@@ -902,6 +915,7 @@
 
         waitForScrollIdle();
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex + 1);
             }
@@ -909,6 +923,7 @@
         // let the scroll running for a while and requestLayout during scroll
         Thread.sleep(80);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 assertEquals(mGridView.getScrollState(), BaseGridView.SCROLL_STATE_SETTLING);
                 mGridView.requestLayout();
@@ -919,6 +934,7 @@
         int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
             }
@@ -941,6 +957,7 @@
 
         final int focusToIndex = mGridView.getChildCount() - 1;
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
@@ -957,6 +974,7 @@
         int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
             }
@@ -984,6 +1002,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(150);
             }
@@ -993,6 +1012,7 @@
         View view =  mGridView.getChildAt(mGridView.getChildCount() - 1);
         final int focusToIndex = mGridView.getChildAdapterPosition(view);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
@@ -1025,6 +1045,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(150);
             }
@@ -1034,6 +1055,7 @@
         View view =  mGridView.getChildAt(mGridView.getChildCount() - 1);
         final int focusToIndex = mGridView.getChildAdapterPosition(view);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
@@ -1061,12 +1083,14 @@
 
         final int focusToIndex = 40;
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
         });
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mActivity.removeItems(focusToIndex, 1);
             }
@@ -1078,6 +1102,7 @@
         int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
             }
@@ -1100,6 +1125,7 @@
 
         final int focusToIndex = 40;
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(focusToIndex);
             }
@@ -1107,6 +1133,7 @@
 
         startWaitLayout();
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 final int removeIndex = mGridView.getChildViewHolder(
                         mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition();
@@ -1121,6 +1148,7 @@
         int leftEdge = mGridView.getLayoutManager().findViewByPosition(focusToIndex).getLeft();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
             }
@@ -1159,6 +1187,7 @@
         assertTrue(mGridView.getLayoutManager().isSmoothScrolling());
         startWaitLayout();
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 final int removeIndex = mGridView.getChildViewHolder(
                         mGridView.getChildAt(mGridView.getChildCount() - 1)).getAdapterPosition();
@@ -1175,6 +1204,7 @@
         int topEdge = mGridView.getLayoutManager().findViewByPosition(focusIndex).getTop();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
             }
@@ -1196,6 +1226,7 @@
         mNumRows = 3;
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mRemovedItems = mActivity.removeItems(0, 200);
             }
@@ -1203,6 +1234,7 @@
 
         humanDelay(500);
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mActivity.addItems(0, mRemovedItems);
             }
@@ -1673,6 +1705,7 @@
 
         final boolean[] scrolled = new boolean[]{false};
         mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy){
                 if (dy > 0) {
                     scrolled[0] = true;
@@ -1705,6 +1738,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(3);
             }
@@ -1745,6 +1779,7 @@
 
         // scroll to invisible item that is far away.
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(100);
             }
@@ -1772,6 +1807,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(10);
             }
@@ -1813,6 +1849,7 @@
 
         // scroll to invisible item that is far away.
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(200);
             }
@@ -1875,6 +1912,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(10);
             }
@@ -1916,6 +1954,7 @@
 
         // scroll to invisible item that is far away.
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(200);
             }
@@ -1943,6 +1982,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(30);
             }
@@ -1982,6 +2022,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(10);
             }
@@ -2021,6 +2062,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(99);
             }
@@ -2030,12 +2072,14 @@
 
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(50);
             }
         });
         Thread.sleep(100);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestLayout();
                 mGridView.setSelectedPositionSmooth(0);
@@ -2102,6 +2146,7 @@
         int targetPosition = items.length - 1;
         mGridView.setSelectedPositionSmooth(targetPosition);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.stopScroll();
             }
@@ -2135,6 +2180,7 @@
         mActivity.addItems(items.length, new int[]{300});
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 ((VerticalGridView) mGridView).setNumColumns(2);
             }
@@ -2163,6 +2209,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(1);
             }
@@ -2194,6 +2241,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(0);
             }
@@ -2202,6 +2250,7 @@
         verifyMargin();
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(1);
             }
@@ -2226,6 +2275,7 @@
         initActivity(intent);
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mActivity.attachToNewAdapter(new int[0]);
             }
@@ -2275,6 +2325,7 @@
 
         // 1 Save view states
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0))
                         .getText()), 0, 1);
@@ -2286,6 +2337,7 @@
 
         // 2 Change view states
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(0))
                         .getText()), 1, 2);
@@ -2296,6 +2348,7 @@
 
         // 3 Detached and re-attached,  should still maintain state of (2)
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(1);
             }
@@ -2308,12 +2361,14 @@
 
         // 4 Recycled and rebound, should load state from (2)
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(20);
             }
         });
         waitForScrollIdle(mVerifyLayout);
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setSelectedPositionSmooth(0);
             }
@@ -2347,6 +2402,7 @@
 
         // 1. Set text selection, save view states should do nothing on child
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < mGridView.getChildCount(); i++) {
                     Selection.setSelection((Spannable)(((TextView) mGridView.getChildAt(i))
@@ -2358,6 +2414,7 @@
 
         // 2. clear the text selection
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 for (int i = 0; i < mGridView.getChildCount(); i++) {
                     Selection.removeSelection((Spannable)(((TextView) mGridView.getChildAt(i))
@@ -2368,6 +2425,7 @@
 
         // 3. Restore view states should be a no-op for child
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.restoreHierarchyState(container);
                 for (int i = 0; i < mGridView.getChildCount(); i++) {
@@ -2620,6 +2678,7 @@
         mNumRows = 1;
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mActivity.addItems(0, new int[]{300, 300});
                 mGridView.setSelectedPosition(0);
@@ -2650,11 +2709,13 @@
         final View firstView = mGridView.getLayoutManager().findViewByPosition(0);
         final View[] selectedViewByTask = new View[1];
         final ViewHolderTask task = new ViewHolderTask() {
+            @Override
             public void run(RecyclerView.ViewHolder viewHolder) {
                 selectedViewByTask[0] = viewHolder.itemView;
             }
         };
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mActivity.removeItems(0, 1);
                 if (smooth) {
@@ -2685,12 +2746,14 @@
 
         final ArrayList<Integer> selectedLog = new ArrayList<Integer>();
         mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
+            @Override
             public void onChildSelected(ViewGroup parent, View view, int position, long id) {
                 selectedLog.add(position);
             }
         });
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 ChangeableViewTypesProvider.setViewType(0, 1);
                 mGridView.getAdapter().notifyItemChanged(0, 1);
@@ -2712,6 +2775,7 @@
         mNumRows = 1;
 
         performAndWaitForAnimation(new Runnable() {
+            @Override
             public void run() {
                 mActivity.addItems(0, new int[]{300, 300});
                 mGridView.setSelectedPositionSmooth(0);
@@ -2737,6 +2801,7 @@
         // add extra layout space
         startWaitLayout();
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setExtraLayoutSpace(extraLayoutSize);
             }
@@ -2755,6 +2820,7 @@
 
         // clear extra layout space
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.setExtraLayoutSpace(0);
                 verifyMargin();
@@ -2906,6 +2972,7 @@
         // item0 and item2 for the best match of focusSearch(FOCUS_LEFT).  The grid widget
         // must override default addFocusables(), not to add item0 or item2.
         mActivity.mAdapterListener = new GridActivity.AdapterListener() {
+            @Override
             public void onBind(RecyclerView.ViewHolder vh, int position) {
                 if (position == 1) {
                     vh.itemView.setPaddingRelative(500, 0, 0, 0);
@@ -2995,6 +3062,7 @@
     void slideInAndWaitIdle(long timeout) throws Throwable {
         // animateIn() would reset position
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateIn();
             }
@@ -3028,6 +3096,7 @@
                 mGridView.getChildAt(0).getTop());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3041,6 +3110,7 @@
         });
         // scrollToPosition() should not affect slideOut status
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.scrollToPosition(0);
             }
@@ -3079,6 +3149,7 @@
                 mGridView.getChildAt(0).getTop());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3092,6 +3163,7 @@
         });
         // smoothScrollToPosition() should not affect slideOut status
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.smoothScrollToPosition(29);
             }
@@ -3131,6 +3203,7 @@
                 mGridView.getChildAt(0).getTop());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3144,6 +3217,7 @@
         });
         // smoothScrollToPosition() should not affect slideOut status
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.scrollToPosition(29);
             }
@@ -3183,6 +3257,7 @@
                 mGridView.getChildAt(0).getTop());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3196,6 +3271,7 @@
         });
         // change adapter should not affect slideOut status
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mActivity.changeItem(0, 200);
             }
@@ -3243,6 +3319,7 @@
                 mGridView.getChildAt(0).getTop());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
                 mActivity.findViewById(R.id.button).requestFocus();
@@ -3256,6 +3333,7 @@
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.requestFocus();
             }
@@ -3294,6 +3372,7 @@
                 mGridView.getChildAt(0).getLeft());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3305,6 +3384,7 @@
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.scrollToPosition(0);
             }
@@ -3346,6 +3426,7 @@
                 mGridView.getChildAt(0).getRight());
 
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.animateOut();
             }
@@ -3358,6 +3439,7 @@
             }
         });
         mActivityTestRule.runOnUiThread(new Runnable() {
+            @Override
             public void run() {
                 mGridView.smoothScrollToPosition(0);
             }
@@ -3377,4 +3459,50 @@
                 mGridView.getChildAt(0).getRight());
     }
 
+    @Test
+    public void testSmoothScrollerOutRange() throws Throwable {
+        Intent intent = new Intent();
+        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
+                R.layout.vertical_linear_with_button_onleft);
+        intent.putExtra(GridActivity.EXTRA_REQUEST_FOCUS_ONLAYOUT, true);
+        int[] items = new int[30];
+        for (int i = 0; i < items.length; i++) {
+            items[i] = 680;
+        }
+        intent.putExtra(GridActivity.EXTRA_ITEMS, items);
+        intent.putExtra(GridActivity.EXTRA_STAGGERED, false);
+        mOrientation = BaseGridView.VERTICAL;
+        mNumRows = 1;
+
+        initActivity(intent);
+
+        final View button = mActivity.findViewById(R.id.button);
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            public void run() {
+                button.requestFocus();
+            }
+        });
+
+        mGridView.setSelectedPositionSmooth(0);
+        waitForScrollIdle(mVerifyLayout);
+
+        mActivityTestRule.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setSelectedPositionSmooth(120);
+            }
+        });
+        waitForScrollIdle(mVerifyLayout);
+        assertTrue(button.hasFocus());
+        int key;
+        if (mGridView.getLayoutDirection() == ViewGroup.LAYOUT_DIRECTION_RTL) {
+            key = KeyEvent.KEYCODE_DPAD_LEFT;
+        } else {
+            key = KeyEvent.KEYCODE_DPAD_RIGHT;
+        }
+        sendKey(key);
+        // the GridView should has focus in its children
+        assertTrue(mGridView.hasFocus());
+        assertFalse(mGridView.isFocused());
+        assertEquals(29, mGridView.getSelectedPosition());
+    }
 }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatEffectTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatEffectTest.java
index 0c98e7d..eca3b9a 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatEffectTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatEffectTest.java
@@ -46,6 +46,7 @@
         MockitoAnnotations.initMocks(this);
         mSource = new Parallax.FloatParallax<Parallax.FloatProperty>() {
 
+            @Override
             public float getMaxValue() {
                 return mScreenMax;
             }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatTest.java
index a2b00b9..23b8b5c 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxFloatTest.java
@@ -43,6 +43,7 @@
     public void setUp() throws Exception {
         mSource = new Parallax.FloatParallax<Parallax.FloatProperty>() {
 
+            @Override
             public float getMaxValue() {
                 return mScreenMax;
             }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntEffectTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntEffectTest.java
index 02b3f69..398a0a8 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntEffectTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntEffectTest.java
@@ -43,6 +43,7 @@
         MockitoAnnotations.initMocks(this);
         mSource = new Parallax.IntParallax<Parallax.IntProperty>() {
 
+            @Override
             public int getMaxValue() {
                 return mScreenMax;
             }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntTest.java
index 84fadbd..e8269ad 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ParallaxIntTest.java
@@ -40,6 +40,7 @@
     public void setUp() throws Exception {
         mSource = new Parallax.IntParallax<Parallax.IntProperty>() {
 
+            @Override
             public int getMaxValue() {
                 return mScreenMax;
             }
diff --git a/v17/preference-leanback/res/layout/leanback_preference_widget_seekbar.xml b/v17/preference-leanback/res/layout/leanback_preference_widget_seekbar.xml
index c121d77..86e2ddf 100644
--- a/v17/preference-leanback/res/layout/leanback_preference_widget_seekbar.xml
+++ b/v17/preference-leanback/res/layout/leanback_preference_widget_seekbar.xml
@@ -28,7 +28,7 @@
               android:clipToPadding="false">
 
     <ImageView
-            android:id="@+android:id/icon"
+            android:id="@android:id/icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
@@ -43,7 +43,7 @@
             android:clipChildren="false"
             android:clipToPadding="false">
 
-        <TextView android:id="@+android:id/title"
+        <TextView android:id="@android:id/title"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
@@ -54,7 +54,7 @@
                   android:textColor="@color/lb_preference_item_primary_text_color"
                   android:textSize="@dimen/lb_preference_item_primary_text_size"/>
 
-        <TextView android:id="@+android:id/summary"
+        <TextView android:id="@android:id/summary"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_below="@android:id/title"
@@ -97,4 +97,4 @@
 
     </RelativeLayout>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java
index 20b36ca..9c1335c 100644
--- a/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java
@@ -39,8 +39,8 @@
 
         final Fragment rawFragment = getTargetFragment();
         if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
-            throw new IllegalStateException("Target fragment must implement TargetFragment" +
-                    " interface");
+            throw new IllegalStateException("Target fragment " + rawFragment
+                    + " must implement TargetFragment interface");
         }
     }
 
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarDrawerToggle.java b/v7/appcompat/src/android/support/v7/app/ActionBarDrawerToggle.java
index 52b7b2e..509c886 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarDrawerToggle.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarDrawerToggle.java
@@ -117,6 +117,7 @@
     private final DrawerLayout mDrawerLayout;
 
     private DrawerArrowDrawable mSlider;
+    private boolean mDrawerSlideAnimationEnabled = true;
     private Drawable mHomeAsUpIndicator;
     boolean mDrawerIndicatorEnabled = true;
     private boolean mHasCustomUpIndicator;
@@ -379,7 +380,7 @@
     /**
      * Sets the DrawerArrowDrawable that should be shown by this ActionBarDrawerToggle.
      *
-     * @param drawable DrawerArrowDrawable that should be shown by this ActionBarDrawerToggle.
+     * @param drawable DrawerArrowDrawable that should be shown by this ActionBarDrawerToggle
      */
     public void setDrawerArrowDrawable(@NonNull DrawerArrowDrawable drawable) {
         mSlider = drawable;
@@ -387,6 +388,25 @@
     }
 
     /**
+     * Specifies whether the drawer arrow should animate when the drawer position changes.
+     *
+     * @param enabled if this is {@code true} then the animation will run, else it will be skipped
+     */
+    public void setDrawerSlideAnimationEnabled(boolean enabled) {
+        mDrawerSlideAnimationEnabled = enabled;
+        if (!enabled) {
+            setPosition(0);
+        }
+    }
+
+    /**
+     * @return whether the drawer slide animation is enabled
+     */
+    public boolean isDrawerSlideAnimationEnabled() {
+        return mDrawerSlideAnimationEnabled;
+    }
+
+    /**
      * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
      * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
      * through to this method from your own listener object.
@@ -396,7 +416,11 @@
      */
     @Override
     public void onDrawerSlide(View drawerView, float slideOffset) {
-        setPosition(Math.min(1f, Math.max(0, slideOffset)));
+        if (mDrawerSlideAnimationEnabled) {
+            setPosition(Math.min(1f, Math.max(0, slideOffset)));
+        } else {
+            setPosition(0); // disable animation.
+        }
     }
 
     /**
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
index 3d37b1f..d2852de 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
@@ -195,14 +195,13 @@
 
     private static AppCompatDelegate create(Context context, Window window,
             AppCompatCallback callback) {
-        final int sdk = Build.VERSION.SDK_INT;
         if (BuildCompat.isAtLeastN()) {
             return new AppCompatDelegateImplN(context, window, callback);
-        } else if (sdk >= 23) {
+        } else if (Build.VERSION.SDK_INT >= 23) {
             return new AppCompatDelegateImplV23(context, window, callback);
-        } else if (sdk >= 14) {
+        } else if (Build.VERSION.SDK_INT >= 14) {
             return new AppCompatDelegateImplV14(context, window, callback);
-        } else if (sdk >= 11) {
+        } else if (Build.VERSION.SDK_INT >= 11) {
             return new AppCompatDelegateImplV11(context, window, callback);
         } else {
             return new AppCompatDelegateImplV9(context, window, callback);
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java b/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
index dd0a4a5..2ac7c99 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
@@ -143,6 +143,7 @@
     /**
      * @hide
      */
+    @Override
     @RestrictTo(LIBRARY_GROUP)
     public void invalidateOptionsMenu() {
         getDelegate().invalidateOptionsMenu();
diff --git a/v7/appcompat/src/android/support/v7/app/NotificationCompat.java b/v7/appcompat/src/android/support/v7/app/NotificationCompat.java
index 17f858b..2f5082a 100644
--- a/v7/appcompat/src/android/support/v7/app/NotificationCompat.java
+++ b/v7/appcompat/src/android/support/v7/app/NotificationCompat.java
@@ -191,6 +191,7 @@
         return new TextAppearanceSpan(null, 0, 0, ColorStateList.valueOf(color), null);
     }
 
+    @RequiresApi(16)
     private static void addMessagingFallBackStyle(MessagingStyle style,
             NotificationBuilderWithBuilderAccessor builder,
             android.support.v4.app.NotificationCompat.Builder b) {
@@ -441,6 +442,7 @@
         }
     }
 
+    @RequiresApi(14)
     private static class IceCreamSandwichExtender extends BuilderExtender {
 
         IceCreamSandwichExtender() {
@@ -462,6 +464,7 @@
         }
     }
 
+    @RequiresApi(16)
     private static class JellybeanExtender extends BuilderExtender {
 
         JellybeanExtender() {
@@ -482,6 +485,7 @@
         }
     }
 
+    @RequiresApi(21)
     private static class LollipopExtender extends BuilderExtender {
 
         LollipopExtender() {
@@ -503,6 +507,7 @@
         }
     }
 
+    @RequiresApi(24)
     private static class Api24Extender extends BuilderExtender {
 
         @Override
diff --git a/v7/appcompat/src/android/support/v7/app/ResourcesFlusher.java b/v7/appcompat/src/android/support/v7/app/ResourcesFlusher.java
index ebfc7cb..8454078 100644
--- a/v7/appcompat/src/android/support/v7/app/ResourcesFlusher.java
+++ b/v7/appcompat/src/android/support/v7/app/ResourcesFlusher.java
@@ -16,7 +16,7 @@
 
 package android.support.v7.app;
 
-import android.annotation.TargetApi;
+import android.support.annotation.RequiresApi;
 import android.content.res.Resources;
 import android.os.Build;
 import android.support.annotation.NonNull;
@@ -52,7 +52,7 @@
         return false;
     }
 
-    @TargetApi(21)
+    @RequiresApi(21)
     private static boolean flushLollipops(@NonNull final Resources resources) {
         if (!sDrawableCacheFieldFetched) {
             try {
@@ -78,7 +78,7 @@
         return false;
     }
 
-    @TargetApi(23)
+    @RequiresApi(23)
     private static boolean flushMarshmallows(@NonNull final Resources resources) {
         if (!sDrawableCacheFieldFetched) {
             try {
@@ -107,7 +107,7 @@
         return drawableCache != null && flushThemedResourcesCache(drawableCache);
     }
 
-    @TargetApi(24)
+    @RequiresApi(24)
     private static boolean flushNougats(@NonNull final Resources resources) {
         if (!sResourcesImplFieldFetched) {
             try {
@@ -158,7 +158,7 @@
         return drawableCache != null && flushThemedResourcesCache(drawableCache);
     }
 
-    @TargetApi(16)
+    @RequiresApi(16)
     private static boolean flushThemedResourcesCache(@NonNull final Object cache) {
         if (!sThemedResourceCacheClazzFetched) {
             try {
diff --git a/v7/appcompat/src/android/support/v7/app/ToolbarActionBar.java b/v7/appcompat/src/android/support/v7/app/ToolbarActionBar.java
index 4776812..c124bc9 100644
--- a/v7/appcompat/src/android/support/v7/app/ToolbarActionBar.java
+++ b/v7/appcompat/src/android/support/v7/app/ToolbarActionBar.java
@@ -491,14 +491,17 @@
         mDecorToolbar.getViewGroup().removeCallbacks(mMenuInvalidator);
     }
 
+    @Override
     public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
         mMenuVisibilityListeners.add(listener);
     }
 
+    @Override
     public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
         mMenuVisibilityListeners.remove(listener);
     }
 
+    @Override
     public void dispatchMenuVisibilityChanged(boolean isVisible) {
         if (isVisible == mLastMenuVisibility) {
             return;
diff --git a/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java b/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
index 3326874..39ff508 100644
--- a/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
+++ b/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
@@ -257,6 +257,7 @@
         return ViewCompat.getElevation(mContainerView);
     }
 
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
     }
@@ -318,6 +319,7 @@
         }
     }
 
+    @Override
     public void onWindowVisibilityChanged(int visibility) {
         mCurWindowVisibility = visibility;
     }
@@ -329,6 +331,7 @@
      *
      * @param enabled true to animate, false to not animate.
      */
+    @Override
     public void setShowHideAnimationEnabled(boolean enabled) {
         mShowHideAnimationEnabled = enabled;
         if (!enabled && mCurrentShowAnim != null) {
@@ -336,14 +339,17 @@
         }
     }
 
+    @Override
     public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
         mMenuVisibilityListeners.add(listener);
     }
 
+    @Override
     public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
         mMenuVisibilityListeners.remove(listener);
     }
 
+    @Override
     public void dispatchMenuVisibilityChanged(boolean isVisible) {
         if (isVisible == mLastMenuVisibility) {
             return;
@@ -402,6 +408,7 @@
         setSubtitle(mContext.getString(resId));
     }
 
+    @Override
     public void setSelectedNavigationItem(int position) {
         switch (mDecorToolbar.getNavigationMode()) {
             case NAVIGATION_MODE_TABS:
@@ -416,6 +423,7 @@
         }
     }
 
+    @Override
     public void removeAllTabs() {
         cleanupTabs();
     }
@@ -431,6 +439,7 @@
         mSavedTabPosition = INVALID_POSITION;
     }
 
+    @Override
     public void setTitle(CharSequence title) {
         mDecorToolbar.setTitle(title);
     }
@@ -450,10 +459,12 @@
         return false;
     }
 
+    @Override
     public void setSubtitle(CharSequence subtitle) {
         mDecorToolbar.setSubtitle(subtitle);
     }
 
+    @Override
     public void setDisplayOptions(int options) {
         if ((options & DISPLAY_HOME_AS_UP) != 0) {
             mDisplayHomeAsUpSet = true;
@@ -461,6 +472,7 @@
         mDecorToolbar.setDisplayOptions(options);
     }
 
+    @Override
     public void setDisplayOptions(int options, int mask) {
         final int current = mDecorToolbar.getDisplayOptions();
         if ((mask & DISPLAY_HOME_AS_UP) != 0) {
@@ -469,38 +481,47 @@
         mDecorToolbar.setDisplayOptions((options & mask) | (current & ~mask));
     }
 
+    @Override
     public void setBackgroundDrawable(Drawable d) {
         mContainerView.setPrimaryBackground(d);
     }
 
+    @Override
     public void setStackedBackgroundDrawable(Drawable d) {
         mContainerView.setStackedBackground(d);
     }
 
+    @Override
     public void setSplitBackgroundDrawable(Drawable d) {
         // no-op. We don't support split action bars
     }
 
+    @Override
     public View getCustomView() {
         return mDecorToolbar.getCustomView();
     }
 
+    @Override
     public CharSequence getTitle() {
         return mDecorToolbar.getTitle();
     }
 
+    @Override
     public CharSequence getSubtitle() {
         return mDecorToolbar.getSubtitle();
     }
 
+    @Override
     public int getNavigationMode() {
         return mDecorToolbar.getNavigationMode();
     }
 
+    @Override
     public int getDisplayOptions() {
         return mDecorToolbar.getDisplayOptions();
     }
 
+    @Override
     public ActionMode startActionMode(ActionMode.Callback callback) {
         if (mActionMode != null) {
             mActionMode.finish();
@@ -651,6 +672,7 @@
         return mContainerView.getHeight();
     }
 
+    @Override
     public void enableContentAnimations(boolean enabled) {
         mContentAnimations = enabled;
     }
@@ -673,6 +695,7 @@
         }
     }
 
+    @Override
     public void showForSystem() {
         if (mHiddenBySystem) {
             mHiddenBySystem = false;
@@ -698,6 +721,7 @@
         }
     }
 
+    @Override
     public void hideForSystem() {
         if (!mHiddenBySystem) {
             mHiddenBySystem = true;
@@ -845,6 +869,7 @@
         }
     }
 
+    @Override
     public boolean isShowing() {
         final int height = getHeight();
         // Take into account the case where the bar has a 0 height due to not being measured yet.
@@ -896,6 +921,7 @@
         return ViewCompat.isLaidOut(mContainerView);
     }
 
+    @Override
     public Context getThemedContext() {
         if (mThemedContext == null) {
             TypedValue outValue = new TypedValue();
@@ -1096,6 +1122,7 @@
             return mCustomView != null ? mCustomView.get() : null;
         }
 
+        @Override
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
             if (mCallback != null) {
                 return mCallback.onActionItemClicked(this, item);
@@ -1123,6 +1150,7 @@
         public void onCloseSubMenu(SubMenuBuilder menu) {
         }
 
+        @Override
         public void onMenuModeChange(MenuBuilder menu) {
             if (mCallback == null) {
                 return;
@@ -1367,6 +1395,7 @@
         return mDecorToolbar.hasLogo();
     }
 
+    @Override
     public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
         if (!mDisplayHomeAsUpSet) {
             setDisplayHomeAsUpEnabled(enable);
diff --git a/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableWrapper.java b/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableWrapper.java
index 9fa45b8..b2406ac 100644
--- a/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableWrapper.java
+++ b/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableWrapper.java
@@ -101,6 +101,7 @@
         return mDrawable.getState();
     }
 
+    @Override
     public void jumpToCurrentState() {
         DrawableCompat.jumpToCurrentState(mDrawable);
     }
@@ -153,6 +154,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void invalidateDrawable(Drawable who) {
         invalidateSelf();
     }
@@ -160,6 +162,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void scheduleDrawable(Drawable who, Runnable what, long when) {
         scheduleSelf(what, when);
     }
@@ -167,6 +170,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void unscheduleDrawable(Drawable who, Runnable what) {
         unscheduleSelf(what);
     }
diff --git a/v7/appcompat/src/android/support/v7/view/StandaloneActionMode.java b/v7/appcompat/src/android/support/v7/view/StandaloneActionMode.java
index 05aff39..bfe98d0 100644
--- a/v7/appcompat/src/android/support/v7/view/StandaloneActionMode.java
+++ b/v7/appcompat/src/android/support/v7/view/StandaloneActionMode.java
@@ -135,6 +135,7 @@
         return new SupportMenuInflater(mContextView.getContext());
     }
 
+    @Override
     public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
         return mCallback.onActionItemClicked(this, item);
     }
@@ -154,11 +155,13 @@
     public void onCloseSubMenu(SubMenuBuilder menu) {
     }
 
+    @Override
     public void onMenuModeChange(MenuBuilder menu) {
         invalidate();
         mContextView.showOverflowMenu();
     }
 
+    @Override
     public boolean isUiFocusable() {
         return mFocusable;
     }
diff --git a/v7/appcompat/src/android/support/v7/view/SupportMenuInflater.java b/v7/appcompat/src/android/support/v7/view/SupportMenuInflater.java
index 7f6424f..60f0f9e 100644
--- a/v7/appcompat/src/android/support/v7/view/SupportMenuInflater.java
+++ b/v7/appcompat/src/android/support/v7/view/SupportMenuInflater.java
@@ -251,6 +251,7 @@
             }
         }
 
+        @Override
         public boolean onMenuItemClick(MenuItem item) {
             try {
                 if (mMethod.getReturnType() == Boolean.TYPE) {
diff --git a/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItem.java b/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItem.java
index bb44131..b3278a4 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItem.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItem.java
@@ -76,75 +76,93 @@
         mTitle = title;
     }
 
+    @Override
     public char getAlphabeticShortcut() {
         return mShortcutAlphabeticChar;
     }
 
+    @Override
     public int getGroupId() {
         return mGroup;
     }
 
+    @Override
     public Drawable getIcon() {
         return mIconDrawable;
     }
 
+    @Override
     public Intent getIntent() {
         return mIntent;
     }
 
+    @Override
     public int getItemId() {
         return mId;
     }
 
+    @Override
     public ContextMenuInfo getMenuInfo() {
         return null;
     }
 
+    @Override
     public char getNumericShortcut() {
         return mShortcutNumericChar;
     }
 
+    @Override
     public int getOrder() {
         return mOrdering;
     }
 
+    @Override
     public SubMenu getSubMenu() {
         return null;
     }
 
+    @Override
     public CharSequence getTitle() {
         return mTitle;
     }
 
+    @Override
     public CharSequence getTitleCondensed() {
         return mTitleCondensed != null ? mTitleCondensed : mTitle;
     }
 
+    @Override
     public boolean hasSubMenu() {
         return false;
     }
 
+    @Override
     public boolean isCheckable() {
         return (mFlags & CHECKABLE) != 0;
     }
 
+    @Override
     public boolean isChecked() {
         return (mFlags & CHECKED) != 0;
     }
 
+    @Override
     public boolean isEnabled() {
         return (mFlags & ENABLED) != 0;
     }
 
+    @Override
     public boolean isVisible() {
         return (mFlags & HIDDEN) == 0;
     }
 
+    @Override
     public MenuItem setAlphabeticShortcut(char alphaChar) {
         mShortcutAlphabeticChar = alphaChar;
         return this;
     }
 
+    @Override
     public MenuItem setCheckable(boolean checkable) {
         mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0);
         return this;
@@ -155,64 +173,76 @@
         return this;
     }
 
+    @Override
     public MenuItem setChecked(boolean checked) {
         mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0);
         return this;
     }
 
+    @Override
     public MenuItem setEnabled(boolean enabled) {
         mFlags = (mFlags & ~ENABLED) | (enabled ? ENABLED : 0);
         return this;
     }
 
+    @Override
     public MenuItem setIcon(Drawable icon) {
         mIconDrawable = icon;
         mIconResId = NO_ICON;
         return this;
     }
 
+    @Override
     public MenuItem setIcon(int iconRes) {
         mIconResId = iconRes;
         mIconDrawable = ContextCompat.getDrawable(mContext, iconRes);
         return this;
     }
 
+    @Override
     public MenuItem setIntent(Intent intent) {
         mIntent = intent;
         return this;
     }
 
+    @Override
     public MenuItem setNumericShortcut(char numericChar) {
         mShortcutNumericChar = numericChar;
         return this;
     }
 
+    @Override
     public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
         mClickListener = menuItemClickListener;
         return this;
     }
 
+    @Override
     public MenuItem setShortcut(char numericChar, char alphaChar) {
         mShortcutNumericChar = numericChar;
         mShortcutAlphabeticChar = alphaChar;
         return this;
     }
 
+    @Override
     public MenuItem setTitle(CharSequence title) {
         mTitle = title;
         return this;
     }
 
+    @Override
     public MenuItem setTitle(int title) {
         mTitle = mContext.getResources().getString(title);
         return this;
     }
 
+    @Override
     public MenuItem setTitleCondensed(CharSequence title) {
         mTitleCondensed = title;
         return this;
     }
 
+    @Override
     public MenuItem setVisible(boolean visible) {
         mFlags = (mFlags & HIDDEN) | (visible ? 0 : HIDDEN);
         return this;
@@ -231,14 +261,17 @@
         return false;
     }
 
+    @Override
     public void setShowAsAction(int show) {
         // Do nothing. ActionMenuItems always show as action buttons.
     }
 
+    @Override
     public SupportMenuItem setActionView(View actionView) {
         throw new UnsupportedOperationException();
     }
 
+    @Override
     public View getActionView() {
         return null;
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItemView.java b/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItemView.java
index b87e9c6..989e609 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItemView.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/ActionMenuItemView.java
@@ -86,6 +86,7 @@
         setSaveEnabled(false);
     }
 
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
@@ -112,10 +113,12 @@
         super.setPadding(l, t, r, b);
     }
 
+    @Override
     public MenuItemImpl getItemData() {
         return mItemData;
     }
 
+    @Override
     public void initialize(MenuItemImpl itemData, int menuType) {
         mItemData = itemData;
 
@@ -156,14 +159,17 @@
         mPopupCallback = popupCallback;
     }
 
+    @Override
     public boolean prefersCondensedTitle() {
         return true;
     }
 
+    @Override
     public void setCheckable(boolean checkable) {
         // TODO Support checkable action items
     }
 
+    @Override
     public void setChecked(boolean checked) {
         // TODO Support checkable action items
     }
@@ -202,6 +208,7 @@
         }
     }
 
+    @Override
     public void setIcon(Drawable icon) {
         mIcon = icon;
         if (icon != null) {
@@ -228,24 +235,29 @@
         return !TextUtils.isEmpty(getText());
     }
 
+    @Override
     public void setShortcut(boolean showShortcut, char shortcutKey) {
         // Action buttons don't show text for shortcut keys.
     }
 
+    @Override
     public void setTitle(CharSequence title) {
         mTitle = title;
 
         updateTextButtonVisibility();
     }
 
+    @Override
     public boolean showsIcon() {
         return true;
     }
 
+    @Override
     public boolean needsDividerBefore() {
         return hasText() && mItemData.getIcon() == null;
     }
 
+    @Override
     public boolean needsDividerAfter() {
         return hasText();
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/BaseMenuPresenter.java b/v7/appcompat/src/android/support/v7/view/menu/BaseMenuPresenter.java
index ff83ae4..1e89ad2 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/BaseMenuPresenter.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/BaseMenuPresenter.java
@@ -85,6 +85,7 @@
     /**
      * Reuses item views when it can
      */
+    @Override
     public void updateMenuView(boolean cleared) {
         final ViewGroup parent = (ViewGroup) mMenuView;
         if (parent == null) return;
@@ -147,6 +148,7 @@
         return true;
     }
 
+    @Override
     public void setCallback(Callback cb) {
         mCallback = cb;
     }
@@ -205,12 +207,14 @@
         return true;
     }
 
+    @Override
     public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
         if (mCallback != null) {
             mCallback.onCloseMenu(menu, allMenusAreClosing);
         }
     }
 
+    @Override
     public boolean onSubMenuSelected(SubMenuBuilder menu) {
         if (mCallback != null) {
             return mCallback.onOpenSubMenu(menu);
@@ -218,18 +222,22 @@
         return false;
     }
 
+    @Override
     public boolean flagActionItems() {
         return false;
     }
 
+    @Override
     public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
         return false;
     }
 
+    @Override
     public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
         return false;
     }
 
+    @Override
     public int getId() {
         return mId;
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/ListMenuItemView.java b/v7/appcompat/src/android/support/v7/view/menu/ListMenuItemView.java
index 855cee2..455eeed 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/ListMenuItemView.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/ListMenuItemView.java
@@ -104,6 +104,7 @@
         }
     }
 
+    @Override
     public void initialize(MenuItemImpl itemData, int menuType) {
         mItemData = itemData;
         mMenuType = menuType;
@@ -123,6 +124,7 @@
         mPreserveIconSpacing = mForceShowIcon = forceShow;
     }
 
+    @Override
     public void setTitle(CharSequence title) {
         if (title != null) {
             mTitleView.setText(title);
@@ -133,10 +135,12 @@
         }
     }
 
+    @Override
     public MenuItemImpl getItemData() {
         return mItemData;
     }
 
+    @Override
     public void setCheckable(boolean checkable) {
         if (!checkable && mRadioButton == null && mCheckBox == null) {
             return;
@@ -183,6 +187,7 @@
         }
     }
 
+    @Override
     public void setChecked(boolean checked) {
         CompoundButton compoundButton;
 
@@ -207,6 +212,7 @@
         }
     }
 
+    @Override
     public void setShortcut(boolean showShortcut, char shortcutKey) {
         final int newVisibility = (showShortcut && mItemData.shouldShowShortcut())
                 ? VISIBLE : GONE;
@@ -220,6 +226,7 @@
         }
     }
 
+    @Override
     public void setIcon(Drawable icon) {
         final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon;
         if (!showIcon && !mPreserveIconSpacing) {
@@ -281,10 +288,12 @@
         addView(mCheckBox);
     }
 
+    @Override
     public boolean prefersCondensedTitle() {
         return false;
     }
 
+    @Override
     public boolean showsIcon() {
         return mForceShowIcon;
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/ListMenuPresenter.java b/v7/appcompat/src/android/support/v7/view/menu/ListMenuPresenter.java
index 41d5576..e3179f4 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/ListMenuPresenter.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/ListMenuPresenter.java
@@ -177,10 +177,12 @@
         return false;
     }
 
+    @Override
     public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
         return false;
     }
 
+    @Override
     public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
         return false;
     }
@@ -232,6 +234,7 @@
             findExpandedIndex();
         }
 
+        @Override
         public int getCount() {
             ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
             int count = items.size() - mItemIndexOffset;
@@ -241,6 +244,7 @@
             return count - 1;
         }
 
+        @Override
         public MenuItemImpl getItem(int position) {
             ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
             position += mItemIndexOffset;
@@ -250,12 +254,14 @@
             return items.get(position);
         }
 
+        @Override
         public long getItemId(int position) {
             // Since a menu item's ID is optional, we'll use the position as an
             // ID for the item in the AdapterView
             return position;
         }
 
+        @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             if (convertView == null) {
                 convertView = mInflater.inflate(mItemLayoutRes, parent, false);
diff --git a/v7/appcompat/src/android/support/v7/view/menu/MenuBuilder.java b/v7/appcompat/src/android/support/v7/view/menu/MenuBuilder.java
index 5f82161..3adfd87 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/MenuBuilder.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/MenuBuilder.java
@@ -460,6 +460,7 @@
                 defaultShowAsAction);
     }
 
+    @Override
     public MenuItem add(CharSequence title) {
         return addInternal(0, 0, 0, title);
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/MenuDialogHelper.java b/v7/appcompat/src/android/support/v7/view/menu/MenuDialogHelper.java
index 6e4036f..eaf7c82 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/MenuDialogHelper.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/MenuDialogHelper.java
@@ -88,6 +88,7 @@
         mDialog.show();
     }
 
+    @Override
     public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) {
             if (event.getAction() == KeyEvent.ACTION_DOWN
@@ -162,6 +163,7 @@
         return false;
     }
 
+    @Override
     public void onClick(DialogInterface dialog, int which) {
         mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0);
     }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/SubMenuBuilder.java b/v7/appcompat/src/android/support/v7/view/menu/SubMenuBuilder.java
index fdd1b14..94300ed 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/SubMenuBuilder.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/SubMenuBuilder.java
@@ -68,6 +68,7 @@
         return mParentMenu;
     }
 
+    @Override
     public MenuItem getItem() {
         return mItem;
     }
@@ -88,32 +89,39 @@
                 mParentMenu.dispatchMenuItemSelected(menu, item);
     }
 
+    @Override
     public SubMenu setIcon(Drawable icon) {
         mItem.setIcon(icon);
         return this;
     }
 
+    @Override
     public SubMenu setIcon(int iconRes) {
         mItem.setIcon(iconRes);
         return this;
     }
 
+    @Override
     public SubMenu setHeaderIcon(Drawable icon) {
         return (SubMenu) super.setHeaderIconInt(icon);
     }
 
+    @Override
     public SubMenu setHeaderIcon(int iconRes) {
         return (SubMenu) super.setHeaderIconInt(iconRes);
     }
 
+    @Override
     public SubMenu setHeaderTitle(CharSequence title) {
         return (SubMenu) super.setHeaderTitleInt(title);
     }
 
+    @Override
     public SubMenu setHeaderTitle(int titleRes) {
         return (SubMenu) super.setHeaderTitleInt(titleRes);
     }
 
+    @Override
     public SubMenu setHeaderView(View view) {
         return (SubMenu) super.setHeaderViewInt(view);
     }
diff --git a/v7/appcompat/src/android/support/v7/widget/AbsActionBarView.java b/v7/appcompat/src/android/support/v7/widget/AbsActionBarView.java
index bab60c4..58a130c 100644
--- a/v7/appcompat/src/android/support/v7/widget/AbsActionBarView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AbsActionBarView.java
@@ -198,6 +198,7 @@
 
     public void postShowOverflowMenu() {
         post(new Runnable() {
+            @Override
             public void run() {
                 showOverflowMenu();
             }
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionBarContainer.java b/v7/appcompat/src/android/support/v7/widget/ActionBarContainer.java
index de4484c..eff105e 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionBarContainer.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionBarContainer.java
@@ -169,6 +169,7 @@
         }
     }
 
+    @Override
     public void jumpDrawablesToCurrentState() {
         if (Build.VERSION.SDK_INT >= 11) {
             super.jumpDrawablesToCurrentState();
@@ -228,12 +229,14 @@
         return mTabContainer;
     }
 
+    @Override
     public android.view.ActionMode startActionModeForChild(View child,
             android.view.ActionMode.Callback callback) {
         // No starting an action mode for an action bar child! (Where would it go?)
         return null;
     }
 
+    @Override
     public android.view.ActionMode startActionModeForChild(View child,
             android.view.ActionMode.Callback callback, int type) {
         if (type != android.view.ActionMode.TYPE_PRIMARY) {
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionBarContextView.java b/v7/appcompat/src/android/support/v7/widget/ActionBarContextView.java
index 4f05080..85554d7 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionBarContextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionBarContextView.java
@@ -92,6 +92,7 @@
         }
     }
 
+    @Override
     public void setContentHeight(int height) {
         mContentHeight = height;
     }
@@ -167,6 +168,7 @@
 
         View closeButton = mClose.findViewById(R.id.action_mode_close_button);
         closeButton.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 mode.finish();
             }
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionBarOverlayLayout.java b/v7/appcompat/src/android/support/v7/widget/ActionBarOverlayLayout.java
index fff6b99..1e4fd35 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionBarOverlayLayout.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionBarOverlayLayout.java
@@ -106,6 +106,7 @@
     };
 
     private final Runnable mRemoveActionBarHideOffset = new Runnable() {
+        @Override
         public void run() {
             haltActionBarHideOffsetAnimations();
             mCurrentActionBarTopAnimator = mActionBarTop.animate().translationY(0)
@@ -114,6 +115,7 @@
     };
 
     private final Runnable mAddActionBarHideOffset = new Runnable() {
+        @Override
         public void run() {
             haltActionBarHideOffsetAnimations();
             mCurrentActionBarTopAnimator = mActionBarTop.animate()
@@ -214,12 +216,14 @@
 //        }
     }
 
+    @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         init(getContext());
         ViewCompat.requestApplyInsets(this);
     }
 
+    @Override
     public void onWindowSystemUiVisibilityChanged(int visible) {
         if (Build.VERSION.SDK_INT >= 16) {
             super.onWindowSystemUiVisibilityChanged(visible);
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
index 05f17fd..888d33b 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
@@ -285,6 +285,7 @@
         return super.filterLeftoverView(parent, childIndex);
     }
 
+    @Override
     public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
         if (!subMenu.hasVisibleItems()) return false;
 
@@ -418,6 +419,7 @@
         return mReserveOverflow;
     }
 
+    @Override
     public boolean flagActionItems() {
         final ArrayList<MenuItemImpl> visibleItems;
         final int itemsSize;
@@ -626,10 +628,12 @@
 
         public static final Parcelable.Creator<SavedState> CREATOR
                 = new Parcelable.Creator<SavedState>() {
+            @Override
             public SavedState createFromParcel(Parcel in) {
                 return new SavedState(in);
             }
 
+            @Override
             public SavedState[] newArray(int size) {
                 return new SavedState[size];
             }
@@ -798,6 +802,7 @@
             mPopup = popup;
         }
 
+        @Override
         public void run() {
             if (mMenu != null) {
                 mMenu.changeMenuMode();
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java b/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
index da56faa..517771b 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
@@ -618,18 +618,21 @@
     }
 
     /** @hide */
+    @Override
     @RestrictTo(LIBRARY_GROUP)
     public boolean invokeItem(MenuItemImpl item) {
         return mMenu.performItemAction(item, 0);
     }
 
     /** @hide */
+    @Override
     @RestrictTo(LIBRARY_GROUP)
     public int getWindowAnimations() {
         return 0;
     }
 
     /** @hide */
+    @Override
     @RestrictTo(LIBRARY_GROUP)
     public void initialize(MenuBuilder menu) {
         mMenu = menu;
@@ -741,6 +744,7 @@
         return result;
     }
 
+    @Override
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
         return false;
     }
diff --git a/v7/appcompat/src/android/support/v7/widget/ActivityChooserModel.java b/v7/appcompat/src/android/support/v7/widget/ActivityChooserModel.java
index ad641df..2aa4cb5 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActivityChooserModel.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActivityChooserModel.java
@@ -893,6 +893,7 @@
             return true;
         }
 
+        @Override
         public int compareTo(ActivityResolveInfo another) {
             return  Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
         }
@@ -920,6 +921,7 @@
         DefaultSorter() {
         }
 
+        @Override
         public void sort(Intent intent, List<ActivityResolveInfo> activities,
                 List<HistoricalRecord> historicalRecords) {
             Map<ComponentName, ActivityResolveInfo> componentNameToActivityMap =
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java b/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java
index f8280c9..ab2c0d1 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatImageButton.java
@@ -152,6 +152,7 @@
         }
     }
 
+    @Override
     public boolean hasOverlappingRendering() {
         return mImageHelper.hasOverlappingRendering() && super.hasOverlappingRendering();
     }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java
index b749d6c..d508ebd 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatImageView.java
@@ -161,6 +161,7 @@
         }
     }
 
+    @Override
     public boolean hasOverlappingRendering() {
         return mImageHelper.hasOverlappingRendering() && super.hasOverlappingRendering();
     }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
index 9f27f78..51e0aa4 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
@@ -290,6 +290,7 @@
     /**
      * @return the context used to inflate the Spinner's popup or dialog window
      */
+    @Override
     public Context getPopupContext() {
         if (mPopup != null) {
             return mPopupContext;
@@ -299,6 +300,7 @@
         return null;
     }
 
+    @Override
     public void setPopupBackgroundDrawable(Drawable background) {
         if (mPopup != null) {
             mPopup.setBackgroundDrawable(background);
@@ -307,10 +309,12 @@
         }
     }
 
+    @Override
     public void setPopupBackgroundResource(@DrawableRes int resId) {
         setPopupBackgroundDrawable(AppCompatResources.getDrawable(getPopupContext(), resId));
     }
 
+    @Override
     public Drawable getPopupBackground() {
         if (mPopup != null) {
             return mPopup.getBackground();
@@ -320,6 +324,7 @@
         return null;
     }
 
+    @Override
     public void setDropDownVerticalOffset(int pixels) {
         if (mPopup != null) {
             mPopup.setVerticalOffset(pixels);
@@ -328,6 +333,7 @@
         }
     }
 
+    @Override
     public int getDropDownVerticalOffset() {
         if (mPopup != null) {
             return mPopup.getVerticalOffset();
@@ -337,6 +343,7 @@
         return 0;
     }
 
+    @Override
     public void setDropDownHorizontalOffset(int pixels) {
         if (mPopup != null) {
             mPopup.setHorizontalOffset(pixels);
@@ -351,6 +358,7 @@
      *
      * @return Horizontal offset in pixels
      */
+    @Override
     public int getDropDownHorizontalOffset() {
         if (mPopup != null) {
             return mPopup.getHorizontalOffset();
@@ -360,6 +368,7 @@
         return 0;
     }
 
+    @Override
     public void setDropDownWidth(int pixels) {
         if (mPopup != null) {
             mDropDownWidth = pixels;
@@ -368,6 +377,7 @@
         }
     }
 
+    @Override
     public int getDropDownWidth() {
         if (mPopup != null) {
             return mDropDownWidth;
@@ -620,37 +630,45 @@
             }
         }
 
+        @Override
         public int getCount() {
             return mAdapter == null ? 0 : mAdapter.getCount();
         }
 
+        @Override
         public Object getItem(int position) {
             return mAdapter == null ? null : mAdapter.getItem(position);
         }
 
+        @Override
         public long getItemId(int position) {
             return mAdapter == null ? -1 : mAdapter.getItemId(position);
         }
 
+        @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             return getDropDownView(position, convertView, parent);
         }
 
+        @Override
         public View getDropDownView(int position, View convertView, ViewGroup parent) {
             return (mAdapter == null) ? null
                     : mAdapter.getDropDownView(position, convertView, parent);
         }
 
+        @Override
         public boolean hasStableIds() {
             return mAdapter != null && mAdapter.hasStableIds();
         }
 
+        @Override
         public void registerDataSetObserver(DataSetObserver observer) {
             if (mAdapter != null) {
                 mAdapter.registerDataSetObserver(observer);
             }
         }
 
+        @Override
         public void unregisterDataSetObserver(DataSetObserver observer) {
             if (mAdapter != null) {
                 mAdapter.unregisterDataSetObserver(observer);
@@ -661,6 +679,7 @@
          * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
          * Otherwise, return true.
          */
+        @Override
         public boolean areAllItemsEnabled() {
             final ListAdapter adapter = mListAdapter;
             if (adapter != null) {
@@ -674,6 +693,7 @@
          * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
          * Otherwise, return true.
          */
+        @Override
         public boolean isEnabled(int position) {
             final ListAdapter adapter = mListAdapter;
             if (adapter != null) {
@@ -683,14 +703,17 @@
             }
         }
 
+        @Override
         public int getItemViewType(int position) {
             return 0;
         }
 
+        @Override
         public int getViewTypeCount() {
             return 1;
         }
 
+        @Override
         public boolean isEmpty() {
             return getCount() == 0;
         }
@@ -773,6 +796,7 @@
             setHorizontalOffset(hOffset);
         }
 
+        @Override
         public void show() {
             final boolean wasShowing = isShowing();
 
diff --git a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
index a212c94..c7a3aee 100644
--- a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
@@ -1751,6 +1751,7 @@
         return p instanceof LinearLayoutCompat.LayoutParams;
     }
 
+    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         if (Build.VERSION.SDK_INT >= 14) {
             super.onInitializeAccessibilityEvent(event);
@@ -1758,6 +1759,7 @@
         }
     }
 
+    @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         if (Build.VERSION.SDK_INT >= 14) {
             super.onInitializeAccessibilityNodeInfo(info);
diff --git a/v7/appcompat/src/android/support/v7/widget/SwitchCompat.java b/v7/appcompat/src/android/support/v7/widget/SwitchCompat.java
index 3d2fa6d..72c20b5 100644
--- a/v7/appcompat/src/android/support/v7/widget/SwitchCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/SwitchCompat.java
@@ -17,7 +17,6 @@
 package android.support.v7.widget;
 
 import android.animation.ObjectAnimator;
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -81,7 +80,6 @@
  * @attr ref android.support.v7.appcompat.R.styleable#SwitchCompat_track
  */
 @RequiresApi(14)
-@TargetApi(14)
 public class SwitchCompat extends CompoundButton {
     private static final int THUMB_ANIMATION_DURATION = 250;
 
diff --git a/v7/appcompat/src/android/support/v7/widget/Toolbar.java b/v7/appcompat/src/android/support/v7/widget/Toolbar.java
index 277c1cb..1865df1 100644
--- a/v7/appcompat/src/android/support/v7/widget/Toolbar.java
+++ b/v7/appcompat/src/android/support/v7/widget/Toolbar.java
@@ -476,6 +476,7 @@
         requestLayout();
     }
 
+    @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         if (Build.VERSION.SDK_INT >= 17) {
             super.onRtlPropertiesChanged(layoutDirection);
diff --git a/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
index 3aa7259..ecdc64f 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/BaseBasicsTestCase.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.support.annotation.RequiresApi;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
@@ -77,6 +78,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 16)
+    @RequiresApi(16)
     public void testFitSystemWindowsReachesContent() {
         final FitWindowsContentLayout content =
                 (FitWindowsContentLayout) getActivity().findViewById(R.id.test_content);
@@ -91,6 +93,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 21)
+    @RequiresApi(21)
     public void testOnApplyWindowInsetsReachesContent() {
         final View content = getActivity().findViewById(R.id.test_content);
         assertNotNull(content);
diff --git a/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java b/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
index 0502ad4..64c63a0 100644
--- a/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
+++ b/v7/appcompat/tests/src/android/support/v7/app/LayoutInflaterFactoryTestCase.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import android.support.annotation.RequiresApi;
 import android.content.Context;
 import android.content.res.Resources;
 import android.support.test.annotation.UiThreadTest;
@@ -77,6 +78,7 @@
 
     // Propagation of themed context to children only works on API 11+.
     @SdkSuppress(minSdkVersion = 11)
+    @RequiresApi(11)
     @UiThreadTest
     @Test
     @SmallTest
diff --git a/v7/appcompat/tests/src/android/support/v7/custom/CustomDrawerLayout.java b/v7/appcompat/tests/src/android/support/v7/custom/CustomDrawerLayout.java
index 217ccbc..dc202cd 100644
--- a/v7/appcompat/tests/src/android/support/v7/custom/CustomDrawerLayout.java
+++ b/v7/appcompat/tests/src/android/support/v7/custom/CustomDrawerLayout.java
@@ -38,6 +38,7 @@
         super(context, attrs, defStyle);
     }
 
+    @Override
     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
         mSystemWindowInsetTop = insets.getSystemWindowInsetTop();
         return super.dispatchApplyWindowInsets(insets);
diff --git a/v7/cardview/src/android/support/v7/widget/CardView.java b/v7/cardview/src/android/support/v7/widget/CardView.java
index 3b47a54..17a9cc4 100644
--- a/v7/cardview/src/android/support/v7/widget/CardView.java
+++ b/v7/cardview/src/android/support/v7/widget/CardView.java
@@ -126,6 +126,7 @@
         // NO OP
     }
 
+    @Override
     public void setPaddingRelative(int start, int top, int end, int bottom) {
         // NO OP
     }
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index 5b9d556..6cc8c5d 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -342,7 +342,7 @@
         return super.verifyDrawable(who) || who == mRemoteIndicator;
     }
 
-    //@Override defined in v11
+    @Override
     public void jumpDrawablesToCurrentState() {
         // We can't call super to handle the background so we do it ourselves.
         //super.jumpDrawablesToCurrentState();
diff --git a/v7/mediarouter/src/android/support/v7/media/RemoteControlClientCompat.java b/v7/mediarouter/src/android/support/v7/media/RemoteControlClientCompat.java
index c5dede8..085d6ff 100644
--- a/v7/mediarouter/src/android/support/v7/media/RemoteControlClientCompat.java
+++ b/v7/mediarouter/src/android/support/v7/media/RemoteControlClientCompat.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.media.AudioManager;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 
 import java.lang.ref.WeakReference;
 
@@ -118,6 +119,7 @@
      * other API available to do so in this platform version.  The UserRouteInfo itself
      * is not attached to the MediaRouter so it is transparent to the user.
      */
+    @RequiresApi(16)
     static class JellybeanImpl extends RemoteControlClientCompat {
         private final Object mRouterObj;
         private final Object mUserRouteCategoryObj;
diff --git a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
index 0833be3..42d0b2a 100644
--- a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
+++ b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
@@ -24,6 +24,7 @@
 import android.content.res.Resources;
 import android.media.AudioManager;
 import android.os.Build;
+import android.support.annotation.RequiresApi;
 import android.support.v7.mediarouter.R;
 import android.view.Display;
 
@@ -212,6 +213,7 @@
     /**
      * Jellybean implementation.
      */
+    @RequiresApi(16)
     static class JellybeanImpl extends SystemMediaRouteProvider
             implements MediaRouterJellybean.Callback, MediaRouterJellybean.VolumeCallback {
         private static final ArrayList<IntentFilter> LIVE_AUDIO_CONTROL_FILTERS;
@@ -731,6 +733,7 @@
     /**
      * Jellybean MR1 implementation.
      */
+    @RequiresApi(17)
     private static class JellybeanMr1Impl extends JellybeanImpl
             implements MediaRouterJellybeanMr1.Callback {
         private MediaRouterJellybeanMr1.ActiveScanWorkaround mActiveScanWorkaround;
@@ -807,6 +810,7 @@
     /**
      * Jellybean MR2 implementation.
      */
+    @RequiresApi(18)
     private static class JellybeanMr2Impl extends JellybeanMr1Impl {
         public JellybeanMr2Impl(Context context, SyncCallback syncCallback) {
             super(context, syncCallback);
@@ -864,6 +868,7 @@
     /**
      * Api24 implementation.
      */
+    @RequiresApi(24)
     private static class Api24Impl extends JellybeanMr2Impl {
         public Api24Impl(Context context, SyncCallback syncCallback) {
             super(context, syncCallback);
diff --git a/v7/preference/res/layout/preference_widget_seekbar.xml b/v7/preference/res/layout/preference_widget_seekbar.xml
index 30bc5ff..05a075f 100644
--- a/v7/preference/res/layout/preference_widget_seekbar.xml
+++ b/v7/preference/res/layout/preference_widget_seekbar.xml
@@ -25,7 +25,7 @@
               android:clipToPadding="false">
 
     <ImageView
-            android:id="@+android:id/icon"
+            android:id="@android:id/icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
@@ -42,7 +42,7 @@
             android:clipChildren="false"
             android:clipToPadding="false">
 
-        <TextView android:id="@+android:id/title"
+        <TextView android:id="@android:id/title"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
@@ -50,7 +50,7 @@
                   android:ellipsize="marquee"
                   android:fadingEdge="horizontal"/>
 
-        <TextView android:id="@+android:id/summary"
+        <TextView android:id="@android:id/summary"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_below="@android:id/title"
@@ -94,4 +94,4 @@
 
     </RelativeLayout>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java b/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java
index e2a133c..e9a9dcf 100644
--- a/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java
+++ b/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java
@@ -69,6 +69,7 @@
         super.setMaxWidth(maxWidth);
     }
 
+    @Override
     public int getMaxWidth() {
         return mMaxWidth;
     }
@@ -79,6 +80,7 @@
         super.setMaxHeight(maxHeight);
     }
 
+    @Override
     public int getMaxHeight() {
         return mMaxHeight;
     }
diff --git a/v7/preference/src/android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat.java b/v7/preference/src/android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat.java
index 370c960..791c299 100644
--- a/v7/preference/src/android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat.java
+++ b/v7/preference/src/android/support/v7/preference/MultiSelectListPreferenceDialogFragmentCompat.java
@@ -102,6 +102,7 @@
         }
         builder.setMultiChoiceItems(mEntries, checkedItems,
                 new DialogInterface.OnMultiChoiceClickListener() {
+                    @Override
                     public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                         if (isChecked) {
                             mPreferenceChanged |= mNewValues.add(
diff --git a/v7/preference/src/android/support/v7/preference/SeekBarPreference.java b/v7/preference/src/android/support/v7/preference/SeekBarPreference.java
index 7e843d8..963604c 100644
--- a/v7/preference/src/android/support/v7/preference/SeekBarPreference.java
+++ b/v7/preference/src/android/support/v7/preference/SeekBarPreference.java
@@ -362,10 +362,12 @@
         @SuppressWarnings("unused")
         public static final Parcelable.Creator<SavedState> CREATOR =
                 new Parcelable.Creator<SavedState>() {
+                    @Override
                     public SavedState createFromParcel(Parcel in) {
                         return new SavedState(in);
                     }
 
+                    @Override
                     public SavedState[] newArray(int size) {
                         return new SavedState[size];
                     }
diff --git a/v7/recyclerview/jvm-tests/src/android/support/v7/util/DiffUtilTest.java b/v7/recyclerview/jvm-tests/src/android/support/v7/util/DiffUtilTest.java
index 9315a19..4ac406a 100644
--- a/v7/recyclerview/jvm-tests/src/android/support/v7/util/DiffUtilTest.java
+++ b/v7/recyclerview/jvm-tests/src/android/support/v7/util/DiffUtilTest.java
@@ -22,7 +22,6 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import android.support.annotation.Nullable;
-import android.support.test.filters.LargeTest;
 import android.support.test.filters.SmallTest;
 
 import org.hamcrest.CoreMatchers;
@@ -102,8 +101,9 @@
         check();
     }
 
-    @Test
-    @LargeTest
+    //@Test
+    //@LargeTest
+    // Used for development
     public void testRandom() {
         for (int x = 0; x < 100; x++) {
             for (int i = 0; i < 100; i++) {
diff --git a/v7/recyclerview/jvm-tests/src/android/support/v7/widget/AdapterHelperTest.java b/v7/recyclerview/jvm-tests/src/android/support/v7/widget/AdapterHelperTest.java
index c303c60..e0dbde5 100644
--- a/v7/recyclerview/jvm-tests/src/android/support/v7/widget/AdapterHelperTest.java
+++ b/v7/recyclerview/jvm-tests/src/android/support/v7/widget/AdapterHelperTest.java
@@ -1185,5 +1185,10 @@
         public MockViewHolder(View itemView) {
             super(itemView);
         }
+
+        @Override
+        public String toString() {
+            return mItem == null ? "null" : mItem.toString();
+        }
     }
 }
diff --git a/v7/recyclerview/src/android/support/v7/widget/FastScroller.java b/v7/recyclerview/src/android/support/v7/widget/FastScroller.java
index 1d69ae1..9e45909 100644
--- a/v7/recyclerview/src/android/support/v7/widget/FastScroller.java
+++ b/v7/recyclerview/src/android/support/v7/widget/FastScroller.java
@@ -32,12 +32,16 @@
 import android.support.v7.widget.RecyclerView.OnScrollListener;
 import android.view.MotionEvent;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Class responsible to animate and provide a fast scroller.
  */
 @VisibleForTesting
 class FastScroller extends ItemDecoration implements OnItemTouchListener {
     @IntDef({STATE_HIDDEN, STATE_VISIBLE, STATE_DRAGGING})
+    @Retention(RetentionPolicy.SOURCE)
     private @interface State { }
     // Scroll thumb not showing
     private static final int STATE_HIDDEN = 0;
@@ -47,6 +51,7 @@
     private static final int STATE_DRAGGING = 2;
 
     @IntDef({DRAG_X, DRAG_Y, DRAG_NONE})
+    @Retention(RetentionPolicy.SOURCE)
     private @interface DragState{ }
     private static final int DRAG_NONE = 0;
     private static final int DRAG_X = 1;
@@ -54,6 +59,7 @@
 
     @IntDef({ANIMATION_STATE_OUT, ANIMATION_STATE_FADING_IN, ANIMATION_STATE_IN,
         ANIMATION_STATE_FADING_OUT})
+    @Retention(RetentionPolicy.SOURCE)
     private @interface AnimationState { }
     private static final int ANIMATION_STATE_OUT = 0;
     private static final int ANIMATION_STATE_FADING_IN = 1;
diff --git a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
index 47f7954..b4419cc 100644
--- a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
@@ -148,7 +148,7 @@
     /**
      * Number of items to prefetch when first coming on screen with new data.
      */
-    private int mInitialItemPrefetchCount = 2;
+    private int mInitialPrefetchItemCount = 2;
 
     /**
      * Creates a vertical LinearLayoutManager
@@ -1229,7 +1229,7 @@
                 ? LayoutState.ITEM_DIRECTION_HEAD
                 : LayoutState.ITEM_DIRECTION_TAIL;
         int targetPos = anchorPos;
-        for (int i = 0; i < mInitialItemPrefetchCount; i++) {
+        for (int i = 0; i < mInitialPrefetchItemCount; i++) {
             if (targetPos >= 0 && targetPos < adapterItemCount) {
                 layoutPrefetchRegistry.addPosition(targetPos, 0);
             } else {
@@ -1265,11 +1265,11 @@
      * @param itemCount Number of items to prefetch
      *
      * @see #isItemPrefetchEnabled()
-     * @see #getInitialItemPrefetchCount()
+     * @see #getInitialPrefetchItemCount()
      * @see #collectInitialPrefetchPositions(int, LayoutPrefetchRegistry)
      */
     public void setInitialPrefetchItemCount(int itemCount) {
-        mInitialItemPrefetchCount = itemCount;
+        mInitialPrefetchItemCount = itemCount;
     }
 
     /**
@@ -1284,8 +1284,17 @@
      *
      * @return number of items to prefetch.
      */
+    public int getInitialPrefetchItemCount() {
+        return mInitialPrefetchItemCount;
+    }
+
+
+    /**
+     * @deprecated Use {@link #getInitialPrefetchItemCount()} instead.
+     */
+    @Deprecated
     public int getInitialItemPrefetchCount() {
-        return mInitialItemPrefetchCount;
+        return getInitialPrefetchItemCount();
     }
 
     @Override
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index be2fe9e..511af9d 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -2583,7 +2583,7 @@
     /**
      * Returns true if RecyclerView is attached to window.
      */
-    // @override
+    @Override
     public boolean isAttachedToWindow() {
         return mIsAttached;
     }
@@ -2991,7 +2991,7 @@
         }
     }
 
-    // @Override
+    @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
         if (mLayout == null) {
             return false;
@@ -9229,10 +9229,11 @@
          * bounds.
          *
          * @param child The child view to be examined.
-         * @param completelyVisible If true, the method returns true iff the child is completely
-         *                          visible. If false, the method returns true iff the child is only
-         *                          partially visible (that is it will return false if the child is
-         *                          either completely visible or out of RV's bounds).
+         * @param completelyVisible If true, the method returns true if and only if the child is
+         *                          completely visible. If false, the method returns true if and
+         *                          only if the child is only partially visible (that is it will
+         *                          return false if the child is either completely visible or out
+         *                          of RV's bounds).
          * @param acceptEndPointInclusion If the view's endpoint intersection with RV's start of end
          *                                bounds is enough to consider it partially visible,
          *                                false otherwise.
diff --git a/v7/recyclerview/tests/src/android/support/v7/util/AsyncListUtilTest.java b/v7/recyclerview/tests/src/android/support/v7/util/AsyncListUtilTest.java
index 8766f8c..f8d27ed 100644
--- a/v7/recyclerview/tests/src/android/support/v7/util/AsyncListUtilTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/util/AsyncListUtilTest.java
@@ -210,6 +210,7 @@
             return mDataItemCount;
         }
 
+        @Override
         public int getMaxCachedTiles() {
             return mCacheSize;
         }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/DefaultItemAnimatorTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/DefaultItemAnimatorTest.java
index 4e3cc6b..c28623f 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/DefaultItemAnimatorTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/DefaultItemAnimatorTest.java
@@ -111,6 +111,7 @@
         mDummyParent = getActivity().getContainer();
     }
 
+    @Override
     void checkForMainThreadException() throws Throwable {
         if (mainThreadException != null) {
             throw mainThreadException;
@@ -385,6 +386,7 @@
         return vh;
     }
 
+    @Override
     void postExceptionToInstrumentation(Throwable t) {
         if (mainThreadException == null) {
             mainThreadException = t;
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/DefaultMeasureSpecTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/DefaultMeasureSpecTest.java
index 08da3fb..c756ca0 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/DefaultMeasureSpecTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/DefaultMeasureSpecTest.java
@@ -152,6 +152,7 @@
         runTest();
     }
 
+    @Override
     @Test
     public void runTest() {
         mRecyclerView.defaultOnMeasure(mWSpec, mHSpec);
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewAccessibilityTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewAccessibilityTest.java
index e952370..2a6ca93 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewAccessibilityTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewAccessibilityTest.java
@@ -75,13 +75,13 @@
     @Test
     public void onInitializeAccessibilityNodeInfoTest() throws Throwable {
         final RecyclerView recyclerView = new RecyclerView(getActivity()) {
-            //@Override
+            @Override
             public boolean canScrollHorizontally(int direction) {
                 return direction < 0 && mHorizontalScrollBefore ||
                         direction > 0 && mHorizontalScrollAfter;
             }
 
-            //@Override
+            @Override
             public boolean canScrollVertically(int direction) {
                 return direction < 0 && mVerticalScrollBefore ||
                         direction > 0 && mVerticalScrollAfter;
@@ -240,11 +240,13 @@
     public void ignoreAccessibilityIfAdapterHasChanged() throws Throwable {
         final RecyclerView recyclerView = new RecyclerView(getActivity()) {
             //@Override
+            @Override
             public boolean canScrollHorizontally(int direction) {
                 return true;
             }
 
             //@Override
+            @Override
             public boolean canScrollVertically(int direction) {
                 return true;
             }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewCacheTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewCacheTest.java
index 2ef2783..1b85884 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewCacheTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewCacheTest.java
@@ -787,7 +787,7 @@
     @Test
     public void nestedPrefetchSimple() {
         LinearLayoutManager llm = new LinearLayoutManager(getContext());
-        assertEquals(2, llm.getInitialItemPrefetchCount());
+        assertEquals(2, llm.getInitialPrefetchItemCount());
 
         mRecyclerView.setLayoutManager(llm);
         mRecyclerView.setAdapter(new OuterAdapter());
@@ -1079,7 +1079,7 @@
     @Test
     public void nestedPrefetchDiscardStaleChildren() {
         LinearLayoutManager llm = new LinearLayoutManager(getContext());
-        assertEquals(2, llm.getInitialItemPrefetchCount());
+        assertEquals(2, llm.getInitialPrefetchItemCount());
 
         mRecyclerView.setLayoutManager(llm);
         OuterNotifyAdapter outerAdapter = new OuterNotifyAdapter();
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerSavedStateTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerSavedStateTest.java
index 4757a54..50bdf1b 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerSavedStateTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerSavedStateTest.java
@@ -153,6 +153,7 @@
                 void onBoundItem(TestViewHolder vh, int position) {
                 }
 
+                @Override
                 boolean assignRandomSize() {
                     return false;
                 }