Merge "Fix correctness issues while choosing Adapters for LifecycleObservers" into oc-mr1-support-27.0-dev
diff --git a/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
index ad36b9b..a6a5b2e 100644
--- a/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
@@ -19,7 +19,7 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -115,13 +115,13 @@
 
     private LatchRunnable runOnIO() {
         LatchRunnable latchRunnable = new LatchRunnable();
-        AppToolkitTaskExecutor.getInstance().executeOnDiskIO(latchRunnable);
+        ArchTaskExecutor.getInstance().executeOnDiskIO(latchRunnable);
         return latchRunnable;
     }
 
     private LatchRunnable runOnMain() {
         LatchRunnable latchRunnable = new LatchRunnable();
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(latchRunnable);
+        ArchTaskExecutor.getInstance().executeOnMainThread(latchRunnable);
         return latchRunnable;
     }
 
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
index cd4f8f5..c3366f3 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
@@ -46,11 +46,11 @@
     }
 
     private void beforeStart() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(mTaskExecutor);
+        ArchTaskExecutor.getInstance().setDelegate(mTaskExecutor);
     }
 
     private void afterFinished() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     public TaskExecutor getTaskExecutor() {
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
index ad930aa..77133d5 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
@@ -16,7 +16,7 @@
 
 package android.arch.core.executor.testing;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.DefaultTaskExecutor;
 import android.os.SystemClock;
 
@@ -39,7 +39,7 @@
     @Override
     protected void starting(Description description) {
         super.starting(description);
-        AppToolkitTaskExecutor.getInstance().setDelegate(new DefaultTaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new DefaultTaskExecutor() {
             @Override
             public void executeOnDiskIO(Runnable runnable) {
                 super.executeOnDiskIO(new CountingRunnable(runnable));
@@ -55,7 +55,7 @@
     @Override
     protected void finished(Description description) {
         super.finished(description);
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     private void increment() {
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
index 07dcf1f..f88a3e3 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
@@ -16,7 +16,7 @@
 
 package android.arch.core.executor.testing;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 
 import org.junit.rules.TestWatcher;
@@ -32,7 +32,7 @@
     @Override
     protected void starting(Description description) {
         super.starting(description);
-        AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
             @Override
             public void executeOnDiskIO(Runnable runnable) {
                 runnable.run();
@@ -53,6 +53,6 @@
     @Override
     protected void finished(Description description) {
         super.finished(description);
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 }
diff --git a/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
index 4345fd1..0fdcbfb 100644
--- a/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
@@ -18,7 +18,7 @@
 
 import static org.junit.Assert.assertTrue;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 
 import org.junit.Rule;
 import org.junit.Test;
@@ -46,7 +46,7 @@
                 return null;
             }
         });
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(check);
+        ArchTaskExecutor.getInstance().executeOnMainThread(check);
         check.get(1, TimeUnit.SECONDS);
     }
 
@@ -60,7 +60,7 @@
                 return null;
             }
         });
-        AppToolkitTaskExecutor.getInstance().executeOnDiskIO(check);
+        ArchTaskExecutor.getInstance().executeOnDiskIO(check);
         check.get(1, TimeUnit.SECONDS);
     }
 }
diff --git a/app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
similarity index 88%
rename from app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java
rename to app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
index 7337f74..2401a73 100644
--- a/app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
@@ -29,8 +29,8 @@
  * @hide This API is not final.
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public class AppToolkitTaskExecutor extends TaskExecutor {
-    private static volatile AppToolkitTaskExecutor sInstance;
+public class ArchTaskExecutor extends TaskExecutor {
+    private static volatile ArchTaskExecutor sInstance;
 
     @NonNull
     private TaskExecutor mDelegate;
@@ -54,7 +54,7 @@
         }
     };
 
-    private AppToolkitTaskExecutor() {
+    private ArchTaskExecutor() {
         mDefaultTaskExecutor = new DefaultTaskExecutor();
         mDelegate = mDefaultTaskExecutor;
     }
@@ -62,15 +62,15 @@
     /**
      * Returns an instance of the task executor.
      *
-     * @return The singleton AppToolkitTaskExecutor.
+     * @return The singleton ArchTaskExecutor.
      */
-    public static AppToolkitTaskExecutor getInstance() {
+    public static ArchTaskExecutor getInstance() {
         if (sInstance != null) {
             return sInstance;
         }
-        synchronized (AppToolkitTaskExecutor.class) {
+        synchronized (ArchTaskExecutor.class) {
             if (sInstance == null) {
-                sInstance = new AppToolkitTaskExecutor();
+                sInstance = new ArchTaskExecutor();
             }
         }
         return sInstance;
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index ec8685d..f09c777 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -64,7 +64,7 @@
 }
 
 def setSdkInLocalPropertiesFile() {
-    ext.buildToolsVersion = '26.0.0'
+    ext.buildToolsVersion = '27.0.0'
     final String fullSdkPath = getFullSdkPath();
     if (file(fullSdkPath).exists()) {
         gradle.ext.currentSdk = 26
diff --git a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
index 3905ca5..0dcd902 100644
--- a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
+++ b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
@@ -20,6 +20,8 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.view.View;
 
 /**
@@ -188,8 +190,9 @@
      * @param packageManager The current package manager
      * @return The localized description.
      */
+    @Nullable
     public static String loadDescription(
-            AccessibilityServiceInfo info, PackageManager packageManager) {
+            @NonNull AccessibilityServiceInfo info, @NonNull PackageManager packageManager) {
         if (Build.VERSION.SDK_INT >= 16) {
             return info.loadDescription(packageManager);
         } else {
@@ -206,6 +209,7 @@
      * @param feedbackType The feedback type.
      * @return The string representation.
      */
+    @NonNull
     public static String feedbackTypeToString(int feedbackType) {
         StringBuilder builder = new StringBuilder();
         builder.append("[");
@@ -245,6 +249,7 @@
      * @param flag The flag.
      * @return The string representation.
      */
+    @Nullable
     public static String flagToString(int flag) {
         switch (flag) {
             case AccessibilityServiceInfo.DEFAULT:
@@ -276,7 +281,7 @@
      * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
      * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS
      */
-    public static int getCapabilities(AccessibilityServiceInfo info) {
+    public static int getCapabilities(@NonNull AccessibilityServiceInfo info) {
         if (Build.VERSION.SDK_INT >= 18) {
             return info.getCapabilities();
         } else {
@@ -296,6 +301,7 @@
      * @param capability The capability.
      * @return The string representation.
      */
+    @NonNull
     public static String capabilityToString(int capability) {
         switch (capability) {
             case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT:
diff --git a/compat/java/android/support/v4/app/ActivityCompat.java b/compat/java/android/support/v4/app/ActivityCompat.java
index a26b64c..2ce5a30 100644
--- a/compat/java/android/support/v4/app/ActivityCompat.java
+++ b/compat/java/android/support/v4/app/ActivityCompat.java
@@ -148,8 +148,8 @@
      *                supplied here; there are no supported definitions for
      *                building it manually.
      */
-    public static void startActivityForResult(Activity activity, Intent intent, int requestCode,
-            @Nullable Bundle options) {
+    public static void startActivityForResult(@NonNull Activity activity, @NonNull Intent intent,
+            int requestCode, @Nullable Bundle options) {
         if (Build.VERSION.SDK_INT >= 16) {
             activity.startActivityForResult(intent, requestCode, options);
         } else {
@@ -183,9 +183,10 @@
      *                supplied here; there are no supported definitions for
      *                building it manually.
      */
-    public static void startIntentSenderForResult(Activity activity, IntentSender intent,
-            int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
-            int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
+    public static void startIntentSenderForResult(@NonNull Activity activity,
+            @NonNull IntentSender intent, int requestCode, @Nullable Intent fillInIntent,
+            int flagsMask, int flagsValues, int extraFlags, @Nullable Bundle options)
+            throws IntentSender.SendIntentException {
         if (Build.VERSION.SDK_INT >= 16) {
             activity.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask,
                     flagsValues, extraFlags, options);
@@ -202,7 +203,7 @@
      * <p>On Android 4.1+ calling this method will call through to the native version of this
      * method. For other platforms {@link Activity#finish()} will be called instead.</p>
      */
-    public static void finishAffinity(Activity activity) {
+    public static void finishAffinity(@NonNull Activity activity) {
         if (Build.VERSION.SDK_INT >= 16) {
             activity.finishAffinity();
         } else {
@@ -219,7 +220,7 @@
      * <p>On Android 4.4 or lower, this method only finishes the Activity with no
      * special exit transition.</p>
      */
-    public static void finishAfterTransition(Activity activity) {
+    public static void finishAfterTransition(@NonNull Activity activity) {
         if (Build.VERSION.SDK_INT >= 21) {
             activity.finishAfterTransition();
         } else {
@@ -244,7 +245,7 @@
      * referrer information, applications can spoof it.</p>
      */
     @Nullable
-    public static Uri getReferrer(Activity activity) {
+    public static Uri getReferrer(@NonNull Activity activity) {
         if (Build.VERSION.SDK_INT >= 22) {
             return activity.getReferrer();
         }
@@ -268,8 +269,8 @@
      *
      * @param callback Used to manipulate shared element transitions on the launched Activity.
      */
-    public static void setEnterSharedElementCallback(Activity activity,
-            SharedElementCallback callback) {
+    public static void setEnterSharedElementCallback(@NonNull Activity activity,
+            @Nullable SharedElementCallback callback) {
         if (Build.VERSION.SDK_INT >= 23) {
             android.app.SharedElementCallback frameworkCallback = callback != null
                     ? new SharedElementCallback23Impl(callback)
@@ -292,8 +293,8 @@
      *
      * @param callback Used to manipulate shared element transitions on the launching Activity.
      */
-    public static void setExitSharedElementCallback(Activity activity,
-            SharedElementCallback callback) {
+    public static void setExitSharedElementCallback(@NonNull Activity activity,
+            @Nullable SharedElementCallback callback) {
         if (Build.VERSION.SDK_INT >= 23) {
             android.app.SharedElementCallback frameworkCallback = callback != null
                     ? new SharedElementCallback23Impl(callback)
@@ -307,13 +308,13 @@
         }
     }
 
-    public static void postponeEnterTransition(Activity activity) {
+    public static void postponeEnterTransition(@NonNull Activity activity) {
         if (Build.VERSION.SDK_INT >= 21) {
             activity.postponeEnterTransition();
         }
     }
 
-    public static void startPostponedEnterTransition(Activity activity) {
+    public static void startPostponedEnterTransition(@NonNull Activity activity) {
         if (Build.VERSION.SDK_INT >= 21) {
             activity.startPostponedEnterTransition();
         }
diff --git a/compat/java/android/support/v4/app/ActivityOptionsCompat.java b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
index 2957c50..6676805 100644
--- a/compat/java/android/support/v4/app/ActivityOptionsCompat.java
+++ b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.support.v4.util.Pair;
@@ -60,7 +61,8 @@
      * @return Returns a new ActivityOptions object that you can use to supply
      * these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptionsCompat makeCustomAnimation(Context context,
+    @NonNull
+    public static ActivityOptionsCompat makeCustomAnimation(@NonNull Context context,
             int enterResId, int exitResId) {
         if (Build.VERSION.SDK_INT >= 16) {
             return createImpl(ActivityOptions.makeCustomAnimation(context, enterResId, exitResId));
@@ -88,7 +90,8 @@
      * @return Returns a new ActivityOptions object that you can use to supply
      * these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptionsCompat makeScaleUpAnimation(View source,
+    @NonNull
+    public static ActivityOptionsCompat makeScaleUpAnimation(@NonNull View source,
             int startX, int startY, int startWidth, int startHeight) {
         if (Build.VERSION.SDK_INT >= 16) {
             return createImpl(ActivityOptions.makeScaleUpAnimation(
@@ -111,7 +114,8 @@
      * @return Returns a new ActivityOptions object that you can use to
      * supply these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptionsCompat makeClipRevealAnimation(View source,
+    @NonNull
+    public static ActivityOptionsCompat makeClipRevealAnimation(@NonNull View source,
             int startX, int startY, int width, int height) {
         if (Build.VERSION.SDK_INT >= 23) {
             return createImpl(ActivityOptions.makeClipRevealAnimation(
@@ -139,8 +143,9 @@
      * @return Returns a new ActivityOptions object that you can use to supply
      * these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(View source,
-            Bitmap thumbnail, int startX, int startY) {
+    @NonNull
+    public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(@NonNull View source,
+            @NonNull Bitmap thumbnail, int startX, int startY) {
         if (Build.VERSION.SDK_INT >= 16) {
             return createImpl(ActivityOptions.makeThumbnailScaleUpAnimation(
                     source, thumbnail, startX, startY));
@@ -166,8 +171,9 @@
      * @return Returns a new ActivityOptions object that you can use to
      *         supply these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
-            View sharedElement, String sharedElementName) {
+    @NonNull
+    public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
+            @NonNull View sharedElement, @NonNull String sharedElementName) {
         if (Build.VERSION.SDK_INT >= 21) {
             return createImpl(ActivityOptions.makeSceneTransitionAnimation(
                     activity, sharedElement, sharedElementName));
@@ -192,8 +198,9 @@
      * @return Returns a new ActivityOptions object that you can use to
      *         supply these options as the options Bundle when starting an activity.
      */
+    @NonNull
     @SuppressWarnings("unchecked")
-    public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
+    public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
             Pair<View, String>... sharedElements) {
         if (Build.VERSION.SDK_INT >= 21) {
             android.util.Pair<View, String>[] pairs = null;
@@ -219,6 +226,7 @@
      * {@link android.R.attr#launchMode launchMode} values of
      * <code>singleInstance</code> or <code>singleTask</code>.
      */
+    @NonNull
     public static ActivityOptionsCompat makeTaskLaunchBehind() {
         if (Build.VERSION.SDK_INT >= 21) {
             return createImpl(ActivityOptions.makeTaskLaunchBehind());
@@ -230,6 +238,7 @@
      * Create a basic ActivityOptions that has no special animation associated with it.
      * Other options can still be set.
      */
+    @NonNull
     public static ActivityOptionsCompat makeBasic() {
         if (Build.VERSION.SDK_INT >= 23) {
             return createImpl(ActivityOptions.makeBasic());
@@ -314,6 +323,7 @@
      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
      * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
      */
+    @NonNull
     public ActivityOptionsCompat setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
         return this;
     }
@@ -335,6 +345,7 @@
      * object; you must not modify it, but can supply it to the startActivity
      * methods that take an options Bundle.
      */
+    @Nullable
     public Bundle toBundle() {
         return null;
     }
@@ -344,7 +355,7 @@
      * otherOptions. Any values defined in otherOptions replace those in the
      * base options.
      */
-    public void update(ActivityOptionsCompat otherOptions) {
+    public void update(@NonNull ActivityOptionsCompat otherOptions) {
         // Do nothing.
     }
 
@@ -372,7 +383,7 @@
      *
      * @param receiver A broadcast receiver that will receive the report.
      */
-    public void requestUsageTimeReport(PendingIntent receiver) {
+    public void requestUsageTimeReport(@NonNull PendingIntent receiver) {
         // Do nothing.
     }
 }
diff --git a/compat/java/android/support/v4/app/AlarmManagerCompat.java b/compat/java/android/support/v4/app/AlarmManagerCompat.java
index 5a4582b..a297cb5 100644
--- a/compat/java/android/support/v4/app/AlarmManagerCompat.java
+++ b/compat/java/android/support/v4/app/AlarmManagerCompat.java
@@ -19,6 +19,7 @@
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.os.Build;
+import android.support.annotation.NonNull;
 
 /**
  * Compatibility library for {@link AlarmManager} with fallbacks for older platforms.
@@ -52,8 +53,8 @@
      * @see android.content.Context#registerReceiver
      * @see android.content.Intent#filterEquals
      */
-    public static void setAlarmClock(AlarmManager alarmManager, long triggerTime,
-            PendingIntent showIntent, PendingIntent operation) {
+    public static void setAlarmClock(@NonNull AlarmManager alarmManager, long triggerTime,
+            @NonNull PendingIntent showIntent, @NonNull PendingIntent operation) {
         if (Build.VERSION.SDK_INT >= 21) {
             alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, showIntent),
                     operation);
@@ -110,8 +111,8 @@
      * @see AlarmManager#RTC
      * @see AlarmManager#RTC_WAKEUP
      */
-    public static void setAndAllowWhileIdle(AlarmManager alarmManager, int type,
-            long triggerAtMillis, PendingIntent operation) {
+    public static void setAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
+            long triggerAtMillis, @NonNull PendingIntent operation) {
         if (Build.VERSION.SDK_INT >= 23) {
             alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
         } else {
@@ -155,8 +156,8 @@
      * @see AlarmManager#RTC
      * @see AlarmManager#RTC_WAKEUP
      */
-    public static void setExact(AlarmManager alarmManager, int type, long triggerAtMillis,
-            PendingIntent operation) {
+    public static void setExact(@NonNull AlarmManager alarmManager, int type, long triggerAtMillis,
+            @NonNull PendingIntent operation) {
         if (Build.VERSION.SDK_INT >= 19) {
             alarmManager.setExact(type, triggerAtMillis, operation);
         } else {
@@ -215,8 +216,8 @@
      * @see AlarmManager#RTC
      * @see AlarmManager#RTC_WAKEUP
      */
-    public static void setExactAndAllowWhileIdle(AlarmManager alarmManager, int type,
-            long triggerAtMillis, PendingIntent operation) {
+    public static void setExactAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
+            long triggerAtMillis, @NonNull PendingIntent operation) {
         if (Build.VERSION.SDK_INT >= 23) {
             alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
         } else {
diff --git a/compat/java/android/support/v4/app/AppOpsManagerCompat.java b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
index ce2d2c6..7e97199 100644
--- a/compat/java/android/support/v4/app/AppOpsManagerCompat.java
+++ b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
@@ -21,6 +21,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 
 /**
  * Helper for accessing features in {@link android.app.AppOpsManager}.
@@ -56,6 +57,7 @@
      * @param permission The permission.
      * @return The app op associated with the permission or null.
      */
+    @Nullable
     public static String permissionToOp(@NonNull String permission) {
         if (SDK_INT >= 23) {
             return AppOpsManager.permissionToOp(permission);
diff --git a/compat/java/android/support/v4/app/BundleCompat.java b/compat/java/android/support/v4/app/BundleCompat.java
index e5fc302..21d730d 100644
--- a/compat/java/android/support/v4/app/BundleCompat.java
+++ b/compat/java/android/support/v4/app/BundleCompat.java
@@ -19,6 +19,8 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.util.Log;
 
 import java.lang.reflect.InvocationTargetException;
@@ -94,7 +96,8 @@
      * @param key    The key to use while getting the {@link IBinder}.
      * @return       The {@link IBinder} that was obtained.
      */
-    public static IBinder getBinder(Bundle bundle, String key) {
+    @Nullable
+    public static IBinder getBinder(@NonNull Bundle bundle, @Nullable String key) {
         if (Build.VERSION.SDK_INT >= 18) {
             return bundle.getBinder(key);
         } else {
@@ -109,7 +112,8 @@
      * @param key    The key to use while putting the {@link IBinder}.
      * @param binder The {@link IBinder} to put.
      */
-    public static void putBinder(Bundle bundle, String key, IBinder binder) {
+    public static void putBinder(@NonNull Bundle bundle, @Nullable String key,
+            @Nullable IBinder binder) {
         if (Build.VERSION.SDK_INT >= 18) {
             bundle.putBinder(key, binder);
         } else {
diff --git a/compat/java/android/support/v4/app/NotificationManagerCompat.java b/compat/java/android/support/v4/app/NotificationManagerCompat.java
index 93775ec..1a0f1bc 100644
--- a/compat/java/android/support/v4/app/NotificationManagerCompat.java
+++ b/compat/java/android/support/v4/app/NotificationManagerCompat.java
@@ -36,6 +36,8 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.support.annotation.GuardedBy;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.util.Log;
 
 import java.lang.reflect.Field;
@@ -144,7 +146,8 @@
     public static final int IMPORTANCE_MAX = 5;
 
     /** Get a {@link NotificationManagerCompat} instance for a provided context. */
-    public static NotificationManagerCompat from(Context context) {
+    @NonNull
+    public static NotificationManagerCompat from(@NonNull Context context) {
         return new NotificationManagerCompat(context);
     }
 
@@ -167,7 +170,7 @@
      * @param tag the string identifier of the notification.
      * @param id the ID of the notification
      */
-    public void cancel(String tag, int id) {
+    public void cancel(@Nullable String tag, int id) {
         mNotificationManager.cancel(tag, id);
         if (Build.VERSION.SDK_INT <= MAX_SIDE_CHANNEL_SDK_VERSION) {
             pushSideChannelQueue(new CancelTask(mContext.getPackageName(), id, tag));
@@ -197,7 +200,7 @@
      * @param id the ID of the notification. The pair (tag, id) must be unique within your app.
      * @param notification the notification to post to the system
     */
-    public void notify(String tag, int id, Notification notification) {
+    public void notify(@Nullable String tag, int id, @NonNull Notification notification) {
         if (useSideChannelForNotification(notification)) {
             pushSideChannelQueue(new NotifyTask(mContext.getPackageName(), id, tag, notification));
             // Cancel this notification in notification manager if it just transitioned to being
@@ -253,7 +256,8 @@
     /**
      * Get the set of packages that have an enabled notification listener component within them.
      */
-    public static Set<String> getEnabledListenerPackages(Context context) {
+    @NonNull
+    public static Set<String> getEnabledListenerPackages(@NonNull Context context) {
         final String enabledNotificationListeners = Settings.Secure.getString(
                 context.getContentResolver(),
                 SETTING_ENABLED_NOTIFICATION_LISTENERS);
diff --git a/compat/java/android/support/v4/app/ServiceCompat.java b/compat/java/android/support/v4/app/ServiceCompat.java
index 1676ee8..2e63b23 100644
--- a/compat/java/android/support/v4/app/ServiceCompat.java
+++ b/compat/java/android/support/v4/app/ServiceCompat.java
@@ -22,6 +22,7 @@
 import android.app.Service;
 import android.os.Build;
 import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
@@ -92,7 +93,7 @@
      * {@link #STOP_FOREGROUND_DETACH}.
      * @see Service#startForeground(int, Notification)
      */
-    public static void stopForeground(Service service, @StopForegroundFlags int flags) {
+    public static void stopForeground(@NonNull Service service, @StopForegroundFlags int flags) {
         if (Build.VERSION.SDK_INT >= 24) {
             service.stopForeground(flags);
         } else {
diff --git a/compat/java/android/support/v4/content/ContextCompat.java b/compat/java/android/support/v4/content/ContextCompat.java
index fdbe32f..8a4fd7a 100644
--- a/compat/java/android/support/v4/content/ContextCompat.java
+++ b/compat/java/android/support/v4/content/ContextCompat.java
@@ -79,7 +79,7 @@
      *                length-1 will correspond to the top activity on the resulting task stack.
      * @return true if the underlying API was available and the call was successful, false otherwise
      */
-    public static boolean startActivities(Context context, Intent[] intents) {
+    public static boolean startActivities(@NonNull Context context, @NonNull Intent[] intents) {
         return startActivities(context, intents, null);
     }
 
@@ -110,7 +110,8 @@
      * See {@link android.content.Context#startActivity(Intent, android.os.Bundle)}
      * @return true if the underlying API was available and the call was successful, false otherwise
      */
-    public static boolean startActivities(Context context, Intent[] intents, Bundle options) {
+    public static boolean startActivities(@NonNull Context context, @NonNull Intent[] intents,
+            @Nullable Bundle options) {
         if (Build.VERSION.SDK_INT >= 16) {
             context.startActivities(intents, options);
         } else {
@@ -136,7 +137,8 @@
      *                supplied here; there are no supported definitions for
      *                building it manually.
      */
-    public static void startActivity(Context context, Intent intent, @Nullable Bundle options) {
+    public static void startActivity(@NonNull Context context, @NonNull Intent intent,
+            @Nullable Bundle options) {
         if (Build.VERSION.SDK_INT >= 16) {
             context.startActivity(intent, options);
         } else {
@@ -159,7 +161,8 @@
      *
      * @see ApplicationInfo#dataDir
      */
-    public static File getDataDir(Context context) {
+    @Nullable
+    public static File getDataDir(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 24) {
             return context.getDataDir();
         } else {
@@ -211,7 +214,8 @@
      * @see Context#getObbDir()
      * @see EnvironmentCompat#getStorageState(File)
      */
-    public static File[] getObbDirs(Context context) {
+    @NonNull
+    public static File[] getObbDirs(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 19) {
             return context.getObbDirs();
         } else {
@@ -263,7 +267,8 @@
      * @see Context#getExternalFilesDir(String)
      * @see EnvironmentCompat#getStorageState(File)
      */
-    public static File[] getExternalFilesDirs(Context context, String type) {
+    @NonNull
+    public static File[] getExternalFilesDirs(@NonNull Context context, @Nullable String type) {
         if (Build.VERSION.SDK_INT >= 19) {
             return context.getExternalFilesDirs(type);
         } else {
@@ -315,7 +320,8 @@
      * @see Context#getExternalCacheDir()
      * @see EnvironmentCompat#getStorageState(File)
      */
-    public static File[] getExternalCacheDirs(Context context) {
+    @NonNull
+    public static File[] getExternalCacheDirs(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 19) {
             return context.getExternalCacheDirs();
         } else {
@@ -346,7 +352,8 @@
      *           The value 0 is an invalid identifier.
      * @return Drawable An object that can be used to draw this resource.
      */
-    public static final Drawable getDrawable(Context context, @DrawableRes int id) {
+    @Nullable
+    public static final Drawable getDrawable(@NonNull Context context, @DrawableRes int id) {
         if (Build.VERSION.SDK_INT >= 21) {
             return context.getDrawable(id);
         } else if (Build.VERSION.SDK_INT >= 16) {
@@ -382,7 +389,9 @@
      * @throws android.content.res.Resources.NotFoundException if the given ID
      *         does not exist.
      */
-    public static final ColorStateList getColorStateList(Context context, @ColorRes int id) {
+    @Nullable
+    public static final ColorStateList getColorStateList(@NonNull Context context,
+            @ColorRes int id) {
         if (Build.VERSION.SDK_INT >= 23) {
             return context.getColorStateList(id);
         } else {
@@ -404,7 +413,7 @@
      *         does not exist.
      */
     @ColorInt
-    public static final int getColor(Context context, @ColorRes int id) {
+    public static final int getColor(@NonNull Context context, @ColorRes int id) {
         if (Build.VERSION.SDK_INT >= 23) {
             return context.getColor(id);
         } else {
@@ -444,7 +453,8 @@
      *
      * @see android.content.Context#getFilesDir()
      */
-    public static final File getNoBackupFilesDir(Context context) {
+    @Nullable
+    public static final File getNoBackupFilesDir(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 21) {
             return context.getNoBackupFilesDir();
         } else {
@@ -468,7 +478,7 @@
      *
      * @return The path of the directory holding application code cache files.
      */
-    public static File getCodeCacheDir(Context context) {
+    public static File getCodeCacheDir(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 21) {
             return context.getCodeCacheDir();
         } else {
@@ -522,7 +532,8 @@
      *
      * @see ContextCompat#isDeviceProtectedStorage(Context)
      */
-    public static Context createDeviceProtectedStorageContext(Context context) {
+    @Nullable
+    public static Context createDeviceProtectedStorageContext(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 24) {
             return context.createDeviceProtectedStorageContext();
         } else {
@@ -536,7 +547,7 @@
      *
      * @see ContextCompat#createDeviceProtectedStorageContext(Context)
      */
-    public static boolean isDeviceProtectedStorage(Context context) {
+    public static boolean isDeviceProtectedStorage(@NonNull Context context) {
         if (Build.VERSION.SDK_INT >= 24) {
             return context.isDeviceProtectedStorage();
         } else {
@@ -554,7 +565,7 @@
      * @see Context#startForegeroundService()
      * @see Context#startService()
      */
-    public static void startForegroundService(Context context, Intent intent) {
+    public static void startForegroundService(@NonNull Context context, @NonNull Intent intent) {
         if (Build.VERSION.SDK_INT >= 26) {
             context.startForegroundService(intent);
         } else {
diff --git a/compat/java/android/support/v4/content/IntentCompat.java b/compat/java/android/support/v4/content/IntentCompat.java
index 1a7295b..f5b3a0b 100644
--- a/compat/java/android/support/v4/content/IntentCompat.java
+++ b/compat/java/android/support/v4/content/IntentCompat.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.os.Build;
+import android.support.annotation.NonNull;
 
 /**
  * Helper for accessing features in {@link android.content.Intent}.
@@ -69,8 +70,9 @@
      * @return Returns a newly created Intent that can be used to launch the
      * activity as a main application entry.
      */
-    public static Intent makeMainSelectorActivity(String selectorAction,
-            String selectorCategory) {
+    @NonNull
+    public static Intent makeMainSelectorActivity(@NonNull String selectorAction,
+            @NonNull String selectorCategory) {
         if (Build.VERSION.SDK_INT >= 15) {
             return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
         } else {
diff --git a/compat/java/android/support/v4/content/res/TypedArrayUtils.java b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
index e4d6b29..64cb981 100644
--- a/compat/java/android/support/v4/content/res/TypedArrayUtils.java
+++ b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -24,6 +24,7 @@
 import android.support.annotation.AnyRes;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.StyleableRes;
 import android.util.AttributeSet;
@@ -80,7 +81,7 @@
      * {@code defaultValue} if it does not exist.
      */
     public static boolean getNamedBoolean(@NonNull TypedArray a, @NonNull XmlPullParser parser,
-            String attrName, @StyleableRes int resId, boolean defaultValue) {
+            @NonNull String attrName, @StyleableRes int resId, boolean defaultValue) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return defaultValue;
@@ -97,7 +98,7 @@
      * {@code defaultValue} if it does not exist.
      */
     public static int getNamedInt(@NonNull TypedArray a, @NonNull XmlPullParser parser,
-            String attrName, @StyleableRes int resId, int defaultValue) {
+            @NonNull String attrName, @StyleableRes int resId, int defaultValue) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return defaultValue;
@@ -115,7 +116,7 @@
      */
     @ColorInt
     public static int getNamedColor(@NonNull TypedArray a, @NonNull XmlPullParser parser,
-            String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
+            @NonNull String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return defaultValue;
@@ -133,7 +134,7 @@
      */
     @AnyRes
     public static int getNamedResourceId(@NonNull TypedArray a, @NonNull XmlPullParser parser,
-            String attrName, @StyleableRes int resId, @AnyRes int defaultValue) {
+            @NonNull String attrName, @StyleableRes int resId, @AnyRes int defaultValue) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return defaultValue;
@@ -149,8 +150,9 @@
      * @return a string value in the {@link TypedArray} with the specified {@code resId}, or
      * null if it does not exist.
      */
+    @Nullable
     public static String getNamedString(@NonNull TypedArray a, @NonNull XmlPullParser parser,
-            String attrName, @StyleableRes int resId) {
+            @NonNull String attrName, @StyleableRes int resId) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return null;
@@ -164,8 +166,9 @@
      * and return a temporary object holding its data.  This object is only
      * valid until the next call on to {@link TypedArray}.
      */
-    public static TypedValue peekNamedValue(TypedArray a, XmlPullParser parser, String attrName,
-            int resId) {
+    @Nullable
+    public static TypedValue peekNamedValue(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+            @NonNull String attrName, int resId) {
         final boolean hasAttr = hasAttribute(parser, attrName);
         if (!hasAttr) {
             return null;
@@ -178,8 +181,9 @@
      * Obtains styled attributes from the theme, if available, or unstyled
      * resources if the theme is null.
      */
-    public static TypedArray obtainAttributes(
-            Resources res, Resources.Theme theme, AttributeSet set, int[] attrs) {
+    @NonNull
+    public static TypedArray obtainAttributes(@NonNull Resources res,
+            @Nullable Resources.Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
         if (theme == null) {
             return res.obtainAttributes(set, attrs);
         }
@@ -190,7 +194,7 @@
      * @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}.
      */
-    public static boolean getBoolean(TypedArray a, @StyleableRes int index,
+    public static boolean getBoolean(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex, boolean defaultValue) {
         boolean val = a.getBoolean(fallbackIndex, defaultValue);
         return a.getBoolean(index, val);
@@ -200,7 +204,8 @@
      * @return a drawable value of {@code index}. If it does not exist, a drawable value of
      * {@code fallbackIndex}. If it still does not exist, {@code null}.
      */
-    public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
+    @Nullable
+    public static Drawable getDrawable(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex) {
         Drawable val = a.getDrawable(index);
         if (val == null) {
@@ -213,7 +218,7 @@
      * @return an int value of {@code index}. If it does not exist, an int value of
      * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
      */
-    public static int getInt(TypedArray a, @StyleableRes int index,
+    public static int getInt(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex, int defaultValue) {
         int val = a.getInt(fallbackIndex, defaultValue);
         return a.getInt(index, val);
@@ -224,7 +229,7 @@
      * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
      */
     @AnyRes
-    public static int getResourceId(TypedArray a, @StyleableRes int index,
+    public static int getResourceId(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
         int val = a.getResourceId(fallbackIndex, defaultValue);
         return a.getResourceId(index, val);
@@ -234,7 +239,8 @@
      * @return a string value of {@code index}. If it does not exist, a string value of
      * {@code fallbackIndex}. If it still does not exist, {@code null}.
      */
-    public static String getString(TypedArray a, @StyleableRes int index,
+    @Nullable
+    public static String getString(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex) {
         String val = a.getString(index);
         if (val == null) {
@@ -249,7 +255,8 @@
      * @return a text value of {@code index}. If it does not exist, a text value of
      * {@code fallbackIndex}. If it still does not exist, {@code null}.
      */
-    public static CharSequence getText(TypedArray a, @StyleableRes int index,
+    @Nullable
+    public static CharSequence getText(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex) {
         CharSequence val = a.getText(index);
         if (val == null) {
@@ -264,7 +271,8 @@
      * @return a string array value of {@code index}. If it does not exist, a string array value
      * of {@code fallbackIndex}. If it still does not exist, {@code null}.
      */
-    public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
+    @Nullable
+    public static CharSequence[] getTextArray(@NonNull TypedArray a, @StyleableRes int index,
             @StyleableRes int fallbackIndex) {
         CharSequence[] val = a.getTextArray(index);
         if (val == null) {
@@ -277,7 +285,7 @@
      * @return The resource ID value in the {@code context} specified by {@code attr}. If it does
      * not exist, {@code fallbackAttr}.
      */
-    public static int getAttr(Context context, int attr, int fallbackAttr) {
+    public static int getAttr(@NonNull Context context, int attr, int fallbackAttr) {
         TypedValue value = new TypedValue();
         context.getTheme().resolveAttribute(attr, value, true);
         if (value.resourceId != 0) {
diff --git a/compat/java/android/support/v4/graphics/BitmapCompat.java b/compat/java/android/support/v4/graphics/BitmapCompat.java
index 20caf80..acc37b1 100644
--- a/compat/java/android/support/v4/graphics/BitmapCompat.java
+++ b/compat/java/android/support/v4/graphics/BitmapCompat.java
@@ -17,6 +17,7 @@
 
 import android.graphics.Bitmap;
 import android.os.Build;
+import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 
 /**
@@ -71,11 +72,11 @@
         }
     }
 
-    public static boolean hasMipMap(Bitmap bitmap) {
+    public static boolean hasMipMap(@NonNull Bitmap bitmap) {
         return IMPL.hasMipMap(bitmap);
     }
 
-    public static void setHasMipMap(Bitmap bitmap, boolean hasMipMap) {
+    public static void setHasMipMap(@NonNull Bitmap bitmap, boolean hasMipMap) {
         IMPL.setHasMipMap(bitmap, hasMipMap);
     }
 
@@ -86,7 +87,7 @@
      * @param bitmap the bitmap in which to return its allocation size
      * @return the allocation size in bytes
      */
-    public static int getAllocationByteCount(Bitmap bitmap) {
+    public static int getAllocationByteCount(@NonNull Bitmap bitmap) {
         return IMPL.getAllocationByteCount(bitmap);
     }
 
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompat.java b/compat/java/android/support/v4/graphics/TypefaceCompat.java
index 6d114b6..b142a5f 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompat.java
@@ -82,7 +82,8 @@
      *
      * @return null if not found.
      */
-    public static Typeface findFromCache(Resources resources, int id, int style) {
+    @Nullable
+    public static Typeface findFromCache(@NonNull Resources resources, int id, int style) {
         return sTypefaceCache.get(createResourceUid(resources, id, style));
     }
 
@@ -103,8 +104,10 @@
      *
      * @return null if failed to create.
      */
+    @Nullable
     public static Typeface createFromResourcesFamilyXml(
-            Context context, FamilyResourceEntry entry, Resources resources, int id, int style,
+            @NonNull Context context, @NonNull FamilyResourceEntry entry,
+            @NonNull Resources resources, int id, int style,
             @Nullable TextView targetView) {
         Typeface typeface;
         if (entry instanceof ProviderResourceEntry) {
@@ -127,7 +130,8 @@
      */
     @Nullable
     public static Typeface createFromResourcesFontFile(
-            Context context, Resources resources, int id, String path, int style) {
+            @NonNull Context context, @NonNull Resources resources, int id, String path,
+            int style) {
         Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile(
                 context, resources, id, path, style);
         if (typeface != null) {
@@ -139,7 +143,8 @@
     /**
      * Create a Typeface from a given FontInfo list and a map that matches them to ByteBuffers.
      */
-    public static Typeface createFromFontInfo(Context context,
+    @Nullable
+    public static Typeface createFromFontInfo(@NonNull Context context,
             @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
         return sTypefaceCompatImpl.createFromFontInfo(context, cancellationSignal, fonts, style);
     }
diff --git a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
index 50d246b..22d39ac 100644
--- a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.view.Display;
 import android.view.WindowManager;
@@ -52,7 +54,8 @@
     /**
      * Gets an instance of the display manager given the context.
      */
-    public static DisplayManagerCompat getInstance(Context context) {
+    @NonNull
+    public static DisplayManagerCompat getInstance(@NonNull Context context) {
         synchronized (sInstances) {
             DisplayManagerCompat instance = sInstances.get(context);
             if (instance == null) {
@@ -76,6 +79,7 @@
      * @param displayId The logical display id.
      * @return The display object, or null if there is no valid display with the given id.
      */
+    @Nullable
     public abstract Display getDisplay(int displayId);
 
     /**
@@ -83,6 +87,7 @@
      *
      * @return An array containing all displays.
      */
+    @NonNull
     public abstract Display[] getDisplays();
 
     /**
@@ -101,6 +106,7 @@
      *
      * @see #DISPLAY_CATEGORY_PRESENTATION
      */
+    @NonNull
     public abstract Display[] getDisplays(String category);
 
     private static class DisplayManagerCompatApi14Impl extends DisplayManagerCompat {
diff --git a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
index 5e23c68..68f9476 100644
--- a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
@@ -44,7 +44,8 @@
     private final Context mContext;
 
     /** Get a {@link FingerprintManagerCompat} instance for a provided context. */
-    public static FingerprintManagerCompat from(Context context) {
+    @NonNull
+    public static FingerprintManagerCompat from(@NonNull Context context) {
         return new FingerprintManagerCompat(context);
     }
 
@@ -119,8 +120,9 @@
         }
     }
 
+    @Nullable
     @RequiresApi(23)
-    private static FingerprintManager getFingerprintManagerOrNull(Context context) {
+    private static FingerprintManager getFingerprintManagerOrNull(@NonNull Context context) {
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
             return context.getSystemService(FingerprintManager.class);
         } else {
@@ -195,20 +197,20 @@
         private final Cipher mCipher;
         private final Mac mMac;
 
-        public CryptoObject(Signature signature) {
+        public CryptoObject(@NonNull Signature signature) {
             mSignature = signature;
             mCipher = null;
             mMac = null;
 
         }
 
-        public CryptoObject(Cipher cipher) {
+        public CryptoObject(@NonNull Cipher cipher) {
             mCipher = cipher;
             mSignature = null;
             mMac = null;
         }
 
-        public CryptoObject(Mac mac) {
+        public CryptoObject(@NonNull Mac mac) {
             mMac = mac;
             mCipher = null;
             mSignature = null;
@@ -218,18 +220,21 @@
          * Get {@link Signature} object.
          * @return {@link Signature} object or null if this doesn't contain one.
          */
+        @Nullable
         public Signature getSignature() { return mSignature; }
 
         /**
          * Get {@link Cipher} object.
          * @return {@link Cipher} object or null if this doesn't contain one.
          */
+        @Nullable
         public Cipher getCipher() { return mCipher; }
 
         /**
          * Get {@link Mac} object.
          * @return {@link Mac} object or null if this doesn't contain one.
          */
+        @Nullable
         public Mac getMac() { return mMac; }
     }
 
diff --git a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
index cdddb68..c08cac8 100644
--- a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
+++ b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
@@ -32,6 +32,8 @@
 import android.net.NetworkInfo;
 import android.os.Build;
 import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresPermission;
 import android.support.annotation.RestrictTo;
 
@@ -91,7 +93,7 @@
      */
     @SuppressWarnings("deprecation")
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
+    public static boolean isActiveNetworkMetered(@NonNull ConnectivityManager cm) {
         if (Build.VERSION.SDK_INT >= 16) {
             return cm.isActiveNetworkMetered();
         } else {
@@ -128,8 +130,10 @@
      * potentially-stale value from
      * {@link ConnectivityManager#EXTRA_NETWORK_INFO}. May be {@code null}.
      */
+    @Nullable
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    public static NetworkInfo getNetworkInfoFromBroadcast(ConnectivityManager cm, Intent intent) {
+    public static NetworkInfo getNetworkInfoFromBroadcast(@NonNull ConnectivityManager cm,
+            @NonNull Intent intent) {
         final NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
         if (info != null) {
             return cm.getNetworkInfo(info.getType());
@@ -147,7 +151,7 @@
      *         or {@link #RESTRICT_BACKGROUND_STATUS_WHITELISTED}
      */
     @RestrictBackgroundStatus
-    public static int getRestrictBackgroundStatus(ConnectivityManager cm) {
+    public static int getRestrictBackgroundStatus(@NonNull ConnectivityManager cm) {
         if (Build.VERSION.SDK_INT >= 24) {
             return cm.getRestrictBackgroundStatus();
         } else {
diff --git a/compat/java/android/support/v4/net/TrafficStatsCompat.java b/compat/java/android/support/v4/net/TrafficStatsCompat.java
index 1049fa5..b74b8d0 100644
--- a/compat/java/android/support/v4/net/TrafficStatsCompat.java
+++ b/compat/java/android/support/v4/net/TrafficStatsCompat.java
@@ -19,6 +19,7 @@
 import android.net.TrafficStats;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
 
 import java.net.DatagramSocket;
 import java.net.Socket;
@@ -131,7 +132,7 @@
      *
      * @see #setThreadStatsTag(int)
      */
-    public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
+    public static void tagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
         if (Build.VERSION.SDK_INT >= 24) {
             TrafficStats.tagDatagramSocket(socket);
         } else {
@@ -148,7 +149,7 @@
     /**
      * Remove any statistics parameters from the given {@link DatagramSocket}.
      */
-    public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
+    public static void untagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
         if (Build.VERSION.SDK_INT >= 24) {
             TrafficStats.untagDatagramSocket(socket);
         } else {
diff --git a/compat/java/android/support/v4/provider/FontRequest.java b/compat/java/android/support/v4/provider/FontRequest.java
index cb32f06..b14f85e 100644
--- a/compat/java/android/support/v4/provider/FontRequest.java
+++ b/compat/java/android/support/v4/provider/FontRequest.java
@@ -89,6 +89,7 @@
      * Returns the selected font provider's authority. This tells the system what font provider
      * it should request the font from.
      */
+    @NonNull
     public String getProviderAuthority() {
         return mProviderAuthority;
     }
@@ -97,6 +98,7 @@
      * Returns the selected font provider's package. This helps the system verify that the provider
      * identified by the given authority is the one requested.
      */
+    @NonNull
     public String getProviderPackage() {
         return mProviderPackage;
     }
@@ -105,6 +107,7 @@
      * Returns the query string. Refer to your font provider's documentation on the format of this
      * string.
      */
+    @NonNull
     public String getQuery() {
         return mQuery;
     }
diff --git a/compat/java/android/support/v4/provider/FontsContractCompat.java b/compat/java/android/support/v4/provider/FontsContractCompat.java
index 6ad46a1..3511f3a 100644
--- a/compat/java/android/support/v4/provider/FontsContractCompat.java
+++ b/compat/java/android/support/v4/provider/FontsContractCompat.java
@@ -600,6 +600,7 @@
      * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
      * @return A Typeface object. Returns null if typeface creation fails.
      */
+    @Nullable
     public static Typeface buildTypeface(@NonNull Context context,
             @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) {
         return TypefaceCompat.createFromFontInfo(context, cancellationSignal, fonts,
diff --git a/compat/java/android/support/v4/util/AtomicFile.java b/compat/java/android/support/v4/util/AtomicFile.java
index 275f4e2..aefe705 100644
--- a/compat/java/android/support/v4/util/AtomicFile.java
+++ b/compat/java/android/support/v4/util/AtomicFile.java
@@ -16,6 +16,8 @@
 
 package android.support.v4.util;
 
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.util.Log;
 
 import java.io.File;
@@ -48,7 +50,7 @@
      * Create a new AtomicFile for a file located at the given File path.
      * The secondary backup file will be the same file path with ".bak" appended.
      */
-    public AtomicFile(File baseName) {
+    public AtomicFile(@NonNull File baseName) {
         mBaseName = baseName;
         mBackupName = new File(baseName.getPath() + ".bak");
     }
@@ -57,6 +59,7 @@
      * Return the path to the base file.  You should not generally use this,
      * as the data at that path may not be valid.
      */
+    @NonNull
     public File getBaseFile() {
         return mBaseName;
     }
@@ -83,6 +86,7 @@
      * safe (or will be lost).  You must do your own threading protection for
      * access to AtomicFile.
      */
+    @NonNull
     public FileOutputStream startWrite() throws IOException {
         // Rename the current file so it may be used as a backup during the next read
         if (mBaseName.exists()) {
@@ -95,7 +99,7 @@
                 mBaseName.delete();
             }
         }
-        FileOutputStream str = null;
+        FileOutputStream str;
         try {
             str = new FileOutputStream(mBaseName);
         } catch (FileNotFoundException e) {
@@ -118,7 +122,7 @@
      * commit the new data.  The next attempt to read the atomic file
      * will return the new file stream.
      */
-    public void finishWrite(FileOutputStream str) {
+    public void finishWrite(@Nullable FileOutputStream str) {
         if (str != null) {
             sync(str);
             try {
@@ -135,7 +139,7 @@
      * returned by {@link #startWrite()}.  This will close the current
      * write stream, and roll back to the previous state of the file.
      */
-    public void failWrite(FileOutputStream str) {
+    public void failWrite(@Nullable FileOutputStream str) {
         if (str != null) {
             sync(str);
             try {
@@ -160,6 +164,7 @@
      * be dropped.  You must do your own threading protection for access to
      * AtomicFile.
      */
+    @NonNull
     public FileInputStream openRead() throws FileNotFoundException {
         if (mBackupName.exists()) {
             mBaseName.delete();
@@ -172,6 +177,7 @@
      * A convenience for {@link #openRead()} that also reads all of the
      * file contents into a byte array which is returned.
      */
+    @NonNull
     public byte[] readFully() throws IOException {
         FileInputStream stream = openRead();
         try {
@@ -200,11 +206,9 @@
         }
     }
 
-    static boolean sync(FileOutputStream stream) {
+    private static boolean sync(@NonNull FileOutputStream stream) {
         try {
-            if (stream != null) {
-                stream.getFD().sync();
-            }
+            stream.getFD().sync();
             return true;
         } catch (IOException e) {
         }
diff --git a/compat/java/android/support/v4/util/ObjectsCompat.java b/compat/java/android/support/v4/util/ObjectsCompat.java
index 4650060..b6c740e 100644
--- a/compat/java/android/support/v4/util/ObjectsCompat.java
+++ b/compat/java/android/support/v4/util/ObjectsCompat.java
@@ -16,6 +16,7 @@
 package android.support.v4.util;
 
 import android.os.Build;
+import android.support.annotation.Nullable;
 
 import java.util.Objects;
 
@@ -43,7 +44,7 @@
      *         and {@code false} otherwise
      * @see Object#equals(Object)
      */
-    public static boolean equals(Object a, Object b) {
+    public static boolean equals(@Nullable Object a, @Nullable Object b) {
         if (Build.VERSION.SDK_INT >= 19) {
             return Objects.equals(a, b);
         } else {
diff --git a/compat/java/android/support/v4/util/Pair.java b/compat/java/android/support/v4/util/Pair.java
index 46ea5cd..9047aec 100644
--- a/compat/java/android/support/v4/util/Pair.java
+++ b/compat/java/android/support/v4/util/Pair.java
@@ -16,14 +16,17 @@
 
 package android.support.v4.util;
 
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
 /**
  * Container to ease passing around a tuple of two objects. This object provides a sensible
  * implementation of equals(), returning true if equals() is true on each of the contained
  * objects.
  */
 public class Pair<F, S> {
-    public final F first;
-    public final S second;
+    public final @Nullable F first;
+    public final @Nullable S second;
 
     /**
      * Constructor for a Pair.
@@ -31,7 +34,7 @@
      * @param first the first object in the Pair
      * @param second the second object in the pair
      */
-    public Pair(F first, S second) {
+    public Pair(@Nullable F first, @Nullable S second) {
         this.first = first;
         this.second = second;
     }
@@ -78,7 +81,8 @@
      * @param b the second object in the pair
      * @return a Pair that is templatized with the types of a and b
      */
-    public static <A, B> Pair <A, B> create(A a, B b) {
+    @NonNull
+    public static <A, B> Pair <A, B> create(@Nullable A a, @Nullable B b) {
         return new Pair<A, B>(a, b);
     }
 }
diff --git a/compat/java/android/support/v4/util/Pools.java b/compat/java/android/support/v4/util/Pools.java
index 6882660..99fd888 100644
--- a/compat/java/android/support/v4/util/Pools.java
+++ b/compat/java/android/support/v4/util/Pools.java
@@ -18,6 +18,9 @@
 package android.support.v4.util;
 
 
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
 /**
  * Helper class for creating pools of objects. An example use looks like this:
  * <pre>
@@ -53,6 +56,7 @@
         /**
          * @return An instance from the pool if such, null otherwise.
          */
+        @Nullable
         public T acquire();
 
         /**
@@ -63,7 +67,7 @@
          *
          * @throws IllegalStateException If the instance is already in the pool.
          */
-        public boolean release(T instance);
+        public boolean release(@NonNull T instance);
     }
 
     private Pools() {
@@ -108,7 +112,7 @@
         }
 
         @Override
-        public boolean release(T instance) {
+        public boolean release(@NonNull T instance) {
             if (isInPool(instance)) {
                 throw new IllegalStateException("Already in the pool!");
             }
@@ -120,7 +124,7 @@
             return false;
         }
 
-        private boolean isInPool(T instance) {
+        private boolean isInPool(@NonNull T instance) {
             for (int i = 0; i < mPoolSize; i++) {
                 if (mPool[i] == instance) {
                     return true;
@@ -157,7 +161,7 @@
         }
 
         @Override
-        public boolean release(T element) {
+        public boolean release(@NonNull T element) {
             synchronized (mLock) {
                 return super.release(element);
             }
diff --git a/compat/java/android/support/v4/widget/EdgeEffectCompat.java b/compat/java/android/support/v4/widget/EdgeEffectCompat.java
index 9293e60..0d370a8 100644
--- a/compat/java/android/support/v4/widget/EdgeEffectCompat.java
+++ b/compat/java/android/support/v4/widget/EdgeEffectCompat.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.os.Build;
+import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.widget.EdgeEffect;
 
@@ -170,7 +171,8 @@
      *
      * @see {@link EdgeEffect#onPull(float, float)}
      */
-    public static void onPull(EdgeEffect edgeEffect, float deltaDistance, float displacement) {
+    public static void onPull(@NonNull EdgeEffect edgeEffect, float deltaDistance,
+            float displacement) {
         IMPL.onPull(edgeEffect, deltaDistance, displacement);
     }
 
diff --git a/compat/java/android/support/v4/widget/ImageViewCompat.java b/compat/java/android/support/v4/widget/ImageViewCompat.java
index acaaf63..b517de5 100644
--- a/compat/java/android/support/v4/widget/ImageViewCompat.java
+++ b/compat/java/android/support/v4/widget/ImageViewCompat.java
@@ -20,6 +20,8 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.widget.ImageView;
 
@@ -130,21 +132,24 @@
     /**
      * Return the tint applied to the image drawable, if specified.
      */
-    public static ColorStateList getImageTintList(ImageView view) {
+    @Nullable
+    public static ColorStateList getImageTintList(@NonNull ImageView view) {
         return IMPL.getImageTintList(view);
     }
 
     /**
      * Applies a tint to the image drawable.
      */
-    public static void setImageTintList(ImageView view, ColorStateList tintList) {
+    public static void setImageTintList(@NonNull ImageView view,
+            @Nullable ColorStateList tintList) {
         IMPL.setImageTintList(view, tintList);
     }
 
     /**
      * Return the blending mode used to apply the tint to the image drawable, if specified.
      */
-    public static PorterDuff.Mode getImageTintMode(ImageView view) {
+    @Nullable
+    public static PorterDuff.Mode getImageTintMode(@NonNull ImageView view) {
         return IMPL.getImageTintMode(view);
     }
 
@@ -153,7 +158,7 @@
      * {@link #setImageTintList(android.widget.ImageView, android.content.res.ColorStateList)}
      * to the image drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
      */
-    public static void setImageTintMode(ImageView view, PorterDuff.Mode mode) {
+    public static void setImageTintMode(@NonNull ImageView view, @Nullable PorterDuff.Mode mode) {
         IMPL.setImageTintMode(view, mode);
     }
 
diff --git a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
index ab86e58..4532733 100644
--- a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
@@ -17,6 +17,8 @@
 package android.support.v4.widget;
 
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.view.View;
 import android.view.View.OnTouchListener;
 import android.widget.ListPopupWindow;
@@ -88,8 +90,9 @@
      * @return a touch listener that controls drag-to-open behavior, or {@code null} on
      *         unsupported APIs
      */
+    @Nullable
     public static OnTouchListener createDragToOpenListener(
-            ListPopupWindow listPopupWindow, View src) {
+            @NonNull ListPopupWindow listPopupWindow, @NonNull View src) {
         if (Build.VERSION.SDK_INT >= 19) {
             return listPopupWindow.createDragToOpenListener(src);
         } else {
diff --git a/compat/java/android/support/v4/widget/PopupMenuCompat.java b/compat/java/android/support/v4/widget/PopupMenuCompat.java
index 639a84b..10c5ff3 100644
--- a/compat/java/android/support/v4/widget/PopupMenuCompat.java
+++ b/compat/java/android/support/v4/widget/PopupMenuCompat.java
@@ -17,6 +17,8 @@
 package android.support.v4.widget;
 
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.view.View.OnTouchListener;
 import android.widget.PopupMenu;
 
@@ -47,7 +49,8 @@
      * @return a touch listener that controls drag-to-open behavior, or {@code null} on
      *         unsupported APIs
      */
-    public static OnTouchListener getDragToOpenListener(Object popupMenu) {
+    @Nullable
+    public static OnTouchListener getDragToOpenListener(@NonNull Object popupMenu) {
         if (Build.VERSION.SDK_INT >= 19) {
             return ((PopupMenu) popupMenu).getDragToOpenListener();
         } else {
diff --git a/compat/java/android/support/v4/widget/PopupWindowCompat.java b/compat/java/android/support/v4/widget/PopupWindowCompat.java
index d846b40..d9de3db 100644
--- a/compat/java/android/support/v4/widget/PopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/PopupWindowCompat.java
@@ -17,6 +17,7 @@
 package android.support.v4.widget;
 
 import android.os.Build;
+import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
@@ -213,8 +214,8 @@
      * @param yoff A vertical offset from the anchor in pixels
      * @param gravity Alignment of the popup relative to the anchor
      */
-    public static void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
-            int gravity) {
+    public static void showAsDropDown(@NonNull PopupWindow popup, @NonNull View anchor,
+            int xoff, int yoff, int gravity) {
         IMPL.showAsDropDown(popup, anchor, xoff, yoff, gravity);
     }
 
@@ -224,7 +225,7 @@
      *
      * @param overlapAnchor Whether the popup should overlap its anchor.
      */
-    public static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+    public static void setOverlapAnchor(@NonNull PopupWindow popupWindow, boolean overlapAnchor) {
         IMPL.setOverlapAnchor(popupWindow, overlapAnchor);
     }
 
@@ -234,7 +235,7 @@
      *
      * @return Whether the popup should overlap its anchor.
      */
-    public static boolean getOverlapAnchor(PopupWindow popupWindow) {
+    public static boolean getOverlapAnchor(@NonNull PopupWindow popupWindow) {
         return IMPL.getOverlapAnchor(popupWindow);
     }
 
@@ -247,7 +248,7 @@
      *
      * @see android.view.WindowManager.LayoutParams#type
      */
-    public static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+    public static void setWindowLayoutType(@NonNull PopupWindow popupWindow, int layoutType) {
         IMPL.setWindowLayoutType(popupWindow, layoutType);
     }
 
@@ -256,7 +257,7 @@
      *
      * @see #setWindowLayoutType(PopupWindow popupWindow, int)
      */
-    public static int getWindowLayoutType(PopupWindow popupWindow) {
+    public static int getWindowLayoutType(@NonNull PopupWindow popupWindow) {
         return IMPL.getWindowLayoutType(popupWindow);
     }
 }
diff --git a/compat/java/android/support/v4/widget/TextViewCompat.java b/compat/java/android/support/v4/widget/TextViewCompat.java
index 8d9e4ab..dc87a38 100644
--- a/compat/java/android/support/v4/widget/TextViewCompat.java
+++ b/compat/java/android/support/v4/widget/TextViewCompat.java
@@ -479,6 +479,7 @@
     /**
      * Returns drawables for the start, top, end, and bottom borders from the given text view.
      */
+    @NonNull
     public static Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView) {
         return IMPL.getCompoundDrawablesRelative(textView);
     }
@@ -493,7 +494,8 @@
      *
      * @attr name android:autoSizeTextType
      */
-    public static void setAutoSizeTextTypeWithDefaults(TextView textView, int autoSizeTextType) {
+    public static void setAutoSizeTextTypeWithDefaults(@NonNull TextView textView,
+            int autoSizeTextType) {
         IMPL.setAutoSizeTextTypeWithDefaults(textView, autoSizeTextType);
     }
 
@@ -519,7 +521,7 @@
      * @attr name android:autoSizeStepGranularity
      */
     public static void setAutoSizeTextTypeUniformWithConfiguration(
-            TextView textView,
+            @NonNull TextView textView,
             int autoSizeMinTextSize,
             int autoSizeMaxTextSize,
             int autoSizeStepGranularity,
@@ -542,7 +544,7 @@
      * @attr name android:autoSizeTextType
      * @attr name android:autoSizePresetSizes
      */
-    public static void setAutoSizeTextTypeUniformWithPresetSizes(TextView textView,
+    public static void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull TextView textView,
             @NonNull int[] presetSizes, int unit) throws IllegalArgumentException {
         IMPL.setAutoSizeTextTypeUniformWithPresetSizes(textView, presetSizes, unit);
     }
@@ -556,7 +558,7 @@
      *
      * @attr name android:autoSizeTextType
      */
-    public static int getAutoSizeTextType(TextView textView) {
+    public static int getAutoSizeTextType(@NonNull TextView textView) {
         return IMPL.getAutoSizeTextType(textView);
     }
 
@@ -565,7 +567,7 @@
      *
      * @attr name android:autoSizeStepGranularity
      */
-    public static int getAutoSizeStepGranularity(TextView textView) {
+    public static int getAutoSizeStepGranularity(@NonNull TextView textView) {
         return IMPL.getAutoSizeStepGranularity(textView);
     }
 
@@ -575,7 +577,7 @@
      *
      * @attr name android:autoSizeMinTextSize
      */
-    public static int getAutoSizeMinTextSize(TextView textView) {
+    public static int getAutoSizeMinTextSize(@NonNull TextView textView) {
         return IMPL.getAutoSizeMinTextSize(textView);
     }
 
@@ -585,7 +587,7 @@
      *
      * @attr name android:autoSizeMaxTextSize
      */
-    public static int getAutoSizeMaxTextSize(TextView textView) {
+    public static int getAutoSizeMaxTextSize(@NonNull TextView textView) {
         return IMPL.getAutoSizeMaxTextSize(textView);
     }
 
@@ -594,7 +596,8 @@
      *
      * @attr name android:autoSizePresetSizes
      */
-    public static int[] getAutoSizeTextAvailableSizes(TextView textView) {
+    @NonNull
+    public static int[] getAutoSizeTextAvailableSizes(@NonNull TextView textView) {
         return IMPL.getAutoSizeTextAvailableSizes(textView);
     }
 }
diff --git a/core-utils/Android.mk b/core-utils/Android.mk
index 6dda862..a6855fc 100644
--- a/core-utils/Android.mk
+++ b/core-utils/Android.mk
@@ -27,9 +27,7 @@
 LOCAL_MODULE := android-support-core-utils
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := \
-    $(call all-java-files-under,kitkat) \
-    $(call all-java-files-under,api21) \
-    $(call all-java-files-under,java)
+    $(call all-java-files-under,src/main/java)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-compat \
diff --git a/core-utils/build.gradle b/core-utils/build.gradle
index 29fe86c..55fe2bb 100644
--- a/core-utils/build.gradle
+++ b/core-utils/build.gradle
@@ -14,14 +14,6 @@
     defaultConfig {
         minSdkVersion 14
     }
-
-    sourceSets {
-        main.java.srcDirs = [
-                'kitkat',
-                'api21',
-                'java'
-        ]
-    }
 }
 
 supportLibrary {
diff --git a/core-utils/java/android/support/v4/app/AppLaunchChecker.java b/core-utils/src/main/java/android/support/v4/app/AppLaunchChecker.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/AppLaunchChecker.java
rename to core-utils/src/main/java/android/support/v4/app/AppLaunchChecker.java
diff --git a/core-utils/java/android/support/v4/app/FrameMetricsAggregator.java b/core-utils/src/main/java/android/support/v4/app/FrameMetricsAggregator.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/FrameMetricsAggregator.java
rename to core-utils/src/main/java/android/support/v4/app/FrameMetricsAggregator.java
diff --git a/core-utils/java/android/support/v4/app/NavUtils.java b/core-utils/src/main/java/android/support/v4/app/NavUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/NavUtils.java
rename to core-utils/src/main/java/android/support/v4/app/NavUtils.java
diff --git a/core-utils/java/android/support/v4/app/TaskStackBuilder.java b/core-utils/src/main/java/android/support/v4/app/TaskStackBuilder.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/TaskStackBuilder.java
rename to core-utils/src/main/java/android/support/v4/app/TaskStackBuilder.java
diff --git a/core-utils/java/android/support/v4/app/package.html b/core-utils/src/main/java/android/support/v4/app/package.html
similarity index 100%
rename from core-utils/java/android/support/v4/app/package.html
rename to core-utils/src/main/java/android/support/v4/app/package.html
diff --git a/core-utils/java/android/support/v4/content/AsyncTaskLoader.java b/core-utils/src/main/java/android/support/v4/content/AsyncTaskLoader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/AsyncTaskLoader.java
rename to core-utils/src/main/java/android/support/v4/content/AsyncTaskLoader.java
diff --git a/core-utils/java/android/support/v4/content/CursorLoader.java b/core-utils/src/main/java/android/support/v4/content/CursorLoader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/CursorLoader.java
rename to core-utils/src/main/java/android/support/v4/content/CursorLoader.java
diff --git a/core-utils/java/android/support/v4/content/FileProvider.java b/core-utils/src/main/java/android/support/v4/content/FileProvider.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/FileProvider.java
rename to core-utils/src/main/java/android/support/v4/content/FileProvider.java
diff --git a/core-utils/java/android/support/v4/content/Loader.java b/core-utils/src/main/java/android/support/v4/content/Loader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/Loader.java
rename to core-utils/src/main/java/android/support/v4/content/Loader.java
diff --git a/core-utils/java/android/support/v4/content/LocalBroadcastManager.java b/core-utils/src/main/java/android/support/v4/content/LocalBroadcastManager.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/LocalBroadcastManager.java
rename to core-utils/src/main/java/android/support/v4/content/LocalBroadcastManager.java
diff --git a/core-utils/java/android/support/v4/content/MimeTypeFilter.java b/core-utils/src/main/java/android/support/v4/content/MimeTypeFilter.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/MimeTypeFilter.java
rename to core-utils/src/main/java/android/support/v4/content/MimeTypeFilter.java
diff --git a/core-utils/java/android/support/v4/content/ModernAsyncTask.java b/core-utils/src/main/java/android/support/v4/content/ModernAsyncTask.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/ModernAsyncTask.java
rename to core-utils/src/main/java/android/support/v4/content/ModernAsyncTask.java
diff --git a/core-utils/java/android/support/v4/content/PermissionChecker.java b/core-utils/src/main/java/android/support/v4/content/PermissionChecker.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/PermissionChecker.java
rename to core-utils/src/main/java/android/support/v4/content/PermissionChecker.java
diff --git a/core-utils/java/android/support/v4/content/WakefulBroadcastReceiver.java b/core-utils/src/main/java/android/support/v4/content/WakefulBroadcastReceiver.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/WakefulBroadcastReceiver.java
rename to core-utils/src/main/java/android/support/v4/content/WakefulBroadcastReceiver.java
diff --git a/core-utils/java/android/support/v4/content/package.html b/core-utils/src/main/java/android/support/v4/content/package.html
similarity index 100%
rename from core-utils/java/android/support/v4/content/package.html
rename to core-utils/src/main/java/android/support/v4/content/package.html
diff --git a/core-utils/java/android/support/v4/graphics/ColorUtils.java b/core-utils/src/main/java/android/support/v4/graphics/ColorUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/ColorUtils.java
rename to core-utils/src/main/java/android/support/v4/graphics/ColorUtils.java
diff --git a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
diff --git a/core-utils/api21/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
similarity index 100%
rename from core-utils/api21/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
diff --git a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
diff --git a/core-utils/java/android/support/v4/math/MathUtils.java b/core-utils/src/main/java/android/support/v4/math/MathUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/math/MathUtils.java
rename to core-utils/src/main/java/android/support/v4/math/MathUtils.java
diff --git a/core-utils/java/android/support/v4/print/PrintHelper.java b/core-utils/src/main/java/android/support/v4/print/PrintHelper.java
similarity index 100%
rename from core-utils/java/android/support/v4/print/PrintHelper.java
rename to core-utils/src/main/java/android/support/v4/print/PrintHelper.java
diff --git a/core-utils/java/android/support/v4/provider/DocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/DocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/DocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/DocumentFile.java
diff --git a/core-utils/kitkat/android/support/v4/provider/DocumentsContractApi19.java b/core-utils/src/main/java/android/support/v4/provider/DocumentsContractApi19.java
similarity index 100%
rename from core-utils/kitkat/android/support/v4/provider/DocumentsContractApi19.java
rename to core-utils/src/main/java/android/support/v4/provider/DocumentsContractApi19.java
diff --git a/core-utils/java/android/support/v4/provider/RawDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/RawDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/RawDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/RawDocumentFile.java
diff --git a/core-utils/java/android/support/v4/provider/SingleDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/SingleDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/SingleDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/SingleDocumentFile.java
diff --git a/core-utils/java/android/support/v4/provider/TreeDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/TreeDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/TreeDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/TreeDocumentFile.java
diff --git a/customtabs/api/current.txt b/customtabs/api/current.txt
index 58cd212..05c16c1 100644
--- a/customtabs/api/current.txt
+++ b/customtabs/api/current.txt
@@ -6,6 +6,7 @@
     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);
+    method public void onRelationshipValidationResult(int, android.net.Uri, boolean, 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
@@ -88,15 +89,21 @@
     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 validateRelationship(android.support.customtabs.CustomTabsSessionToken, int, android.net.Uri, 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 RELATION_HANDLE_ALL_URLS = 2; // 0x2
+    field public static final int RELATION_USE_AS_ORIGIN = 1; // 0x1
     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.Relation implements java.lang.annotation.Annotation {
+  }
+
   public static abstract class CustomTabsService.Result implements java.lang.annotation.Annotation {
   }
 
@@ -113,6 +120,7 @@
     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);
+    method public boolean validateRelationship(int, android.net.Uri, android.os.Bundle);
   }
 
   public class CustomTabsSessionToken {
diff --git a/customtabs/src/android/support/customtabs/CustomTabsCallback.java b/customtabs/src/android/support/customtabs/CustomTabsCallback.java
index 818118a..f8d349a 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsCallback.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsCallback.java
@@ -16,7 +16,9 @@
 
 package android.support.customtabs;
 
+import android.net.Uri;
 import android.os.Bundle;
+import android.support.customtabs.CustomTabsService.Relation;
 
 /**
  * A callback class for custom tabs client to get messages regarding events in their custom tabs. In
@@ -98,4 +100,18 @@
      * @param extras Reserved for future use.
      */
     public void onPostMessage(String message, Bundle extras) {}
+
+    /**
+     * Called when a relationship validation result is available.
+     *
+     * @param relation Relation for which the result is available. Value previously passed to
+     *                 {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. Must be one
+     *                 of the {@code CustomTabsService#RELATION_* } constants.
+     * @param requestedOrigin Origin requested. Value previously passed to
+     *                        {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}.
+     * @param result Whether the relation was validated.
+     * @param extras Reserved for future use.
+     */
+    public void onRelationshipValidationResult(@Relation int relation, Uri requestedOrigin,
+                                               boolean result, Bundle extras) {}
 }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsClient.java b/customtabs/src/android/support/customtabs/CustomTabsClient.java
index 09f3110..2e955cb 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsClient.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsClient.java
@@ -31,6 +31,7 @@
 import android.os.RemoteException;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
+import android.support.customtabs.CustomTabsService.Relation;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -234,6 +235,20 @@
                     }
                 });
             }
+
+            @Override
+            public void onRelationshipValidationResult(
+                    final @Relation int relation, final Uri requestedOrigin, final boolean result,
+                    final @Nullable Bundle extras) throws RemoteException {
+                if (callback == null) return;
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onRelationshipValidationResult(
+                                relation, requestedOrigin, result, extras);
+                    }
+                });
+            }
         };
 
         try {
diff --git a/customtabs/src/android/support/customtabs/CustomTabsService.java b/customtabs/src/android/support/customtabs/CustomTabsService.java
index 5a940cf..aad174c 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsService.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsService.java
@@ -78,6 +78,23 @@
      */
     public static final int RESULT_FAILURE_MESSAGING_ERROR = -3;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({RELATION_USE_AS_ORIGIN, RELATION_HANDLE_ALL_URLS})
+    public @interface Relation {
+    }
+
+    /**
+     * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. For
+     * App -> Web transitions, requests the app to use the declared origin to be used as origin for
+     * the client app in the web APIs context.
+     */
+    public static final int RELATION_USE_AS_ORIGIN = 1;
+    /**
+     * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. Requests the
+     * ability to handle all URLs from a given origin.
+     */
+    public static final int RELATION_HANDLE_ALL_URLS = 2;
+
     private final Map<IBinder, DeathRecipient> mDeathRecipientMap = new ArrayMap<>();
 
     private ICustomTabsService.Stub mBinder = new ICustomTabsService.Stub() {
@@ -137,6 +154,13 @@
             return CustomTabsService.this.postMessage(
                     new CustomTabsSessionToken(callback), message, extras);
         }
+
+        @Override
+        public boolean validateRelationship(
+                ICustomTabsCallback callback, @Relation int relation, Uri origin, Bundle extras) {
+            return CustomTabsService.this.validateRelationship(
+                    new CustomTabsSessionToken(callback), relation, origin, extras);
+        }
     };
 
     @Override
@@ -268,4 +292,23 @@
     @Result
     protected abstract int postMessage(
             CustomTabsSessionToken sessionToken, String message, Bundle extras);
+
+    /**
+     * Request to validate a relationship between the application and an origin.
+     *
+     * If this method returns true, the validation result will be provided through
+     * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}.
+     * Otherwise the request didn't succeed. The client must call
+     * {@link CustomTabsClient#warmup(long)} before this.
+     *
+     * @param sessionToken The unique identifier for the session. Can not be null.
+     * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* }
+     *                 constants.
+     * @param origin Origin for the relation query.
+     * @param extras Reserved for future use.
+     * @return true if the request has been submitted successfully.
+     */
+    protected abstract boolean validateRelationship(
+            CustomTabsSessionToken sessionToken, @Relation int relation, Uri origin,
+            Bundle extras);
 }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSession.java b/customtabs/src/android/support/customtabs/CustomTabsSession.java
index cad897c..d4930ae 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsSession.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsSession.java
@@ -25,6 +25,7 @@
 import android.os.RemoteException;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.customtabs.CustomTabsService.Relation;
 import android.support.customtabs.CustomTabsService.Result;
 import android.view.View;
 import android.widget.RemoteViews;
@@ -185,6 +186,39 @@
         }
     }
 
+    /**
+     * Requests to validate a relationship between the application and an origin.
+     *
+     * <p>
+     * See <a href="https://developers.google.com/digital-asset-links/v1/getting-started">here</a>
+     * for documentation about Digital Asset Links. This methods requests the browser to verify
+     * a relation with the calling application, to grant the associated rights.
+     *
+     * <p>
+     * If this method returns {@code true}, the validation result will be provided through
+     * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}.
+     * Otherwise the request didn't succeed. The client must call
+     * {@link CustomTabsClient#warmup(long)} before this.
+     *
+     * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* }
+     *                 constants.
+     * @param origin Origin.
+     * @param extras Reserved for future use.
+     * @return {@code true} if the request has been submitted successfully.
+     */
+    public boolean validateRelationship(@Relation int relation, @NonNull Uri origin,
+                                        @Nullable Bundle extras) {
+        if (relation < CustomTabsService.RELATION_USE_AS_ORIGIN
+                || relation > CustomTabsService.RELATION_HANDLE_ALL_URLS) {
+            return false;
+        }
+        try {
+            return mService.validateRelationship(mCallback, relation, origin, extras);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     /* package */ IBinder getBinder() {
         return mCallback.asBinder();
     }
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
index adfadd9..ee47278 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
@@ -17,9 +17,11 @@
 package android.support.customtabs;
 
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.support.customtabs.CustomTabsService.Relation;
 import android.support.v4.app.BundleCompat;
 import android.util.Log;
 
@@ -85,6 +87,18 @@
                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
                 }
             }
+
+            @Override
+            public void onRelationshipValidationResult(@Relation int relation, Uri origin,
+                                                       boolean result, Bundle extras) {
+                try {
+                    mCallbackBinder.onRelationshipValidationResult(
+                            relation, origin, result, extras);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
+                }
+            }
+
         };
     }
 
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
index 32b6e9b..3e2c48c 100644
--- a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
+++ b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
@@ -27,4 +27,5 @@
     void extraCallback(String callbackName, in Bundle args) = 2;
     void onMessageChannelReady(in Bundle extras) = 3;
     void onPostMessage(String message, in Bundle extras) = 4;
+    void onRelationshipValidationResult(int relation, in Uri origin, boolean result, in Bundle extras) = 5;
 }
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
index b24b0dd..376c2a4 100644
--- a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
+++ b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
@@ -36,4 +36,5 @@
     boolean updateVisuals(in ICustomTabsCallback callback, in Bundle bundle) = 5;
     boolean requestPostMessageChannel(in ICustomTabsCallback callback, in Uri postMessageOrigin) = 6;
     int postMessage(in ICustomTabsCallback callback, String message, in Bundle extras) = 7;
+    boolean validateRelationship(in ICustomTabsCallback callback, int relation, in Uri origin, in Bundle extras) = 8;
 }
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
index 56b1817..804d354 100644
--- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
+++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
@@ -16,6 +16,7 @@
 
 package android.support.customtabs;
 
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 
@@ -50,6 +51,13 @@
                 throws RemoteException {
             TestCustomTabsCallback.this.onPostMessage(message, extras);
         }
+
+        @Override
+        public void onRelationshipValidationResult(int relation, Uri origin, boolean result,
+                                                   Bundle extras) throws RemoteException {
+            TestCustomTabsCallback.this.onRelationshipValidationResult(
+                    relation, origin, result, extras);
+        }
     };
 
     /* package */ ICustomTabsCallback getStub() {
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
index b5c5e86..e3d5fa8 100644
--- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
+++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
@@ -71,4 +71,10 @@
         if (!mPostMessageRequested) return CustomTabsService.RESULT_FAILURE_DISALLOWED;
         return CustomTabsService.RESULT_SUCCESS;
     }
+
+    @Override
+    protected boolean validateRelationship(CustomTabsSessionToken sessionToken,
+                                           @Relation int relation, Uri origin, Bundle extras) {
+        return false;
+    }
 }
diff --git a/emoji/appcompat/Android.mk b/emoji/appcompat/Android.mk
index 54f6b14..f04d158 100644
--- a/emoji/appcompat/Android.mk
+++ b/emoji/appcompat/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := android-support-emoji-appcompat
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-annotations \
     android-support-v7-appcompat \
diff --git a/emoji/appcompat/build.gradle b/emoji/appcompat/build.gradle
index 9b6e0d4..e22000c 100644
--- a/emoji/appcompat/build.gradle
+++ b/emoji/appcompat/build.gradle
@@ -26,10 +26,6 @@
     defaultConfig {
         minSdkVersion 14
     }
-
-    sourceSets {
-        main.java.srcDir 'src'
-    }
 }
 
 supportLibrary {
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatButton.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatButton.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatButton.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatButton.java
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatEditText.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatEditText.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatEditText.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatEditText.java
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatTextView.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatTextView.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatTextView.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatTextView.java
diff --git a/emoji/bundled/Android.mk b/emoji/bundled/Android.mk
index 3b6b181..29f0d58 100644
--- a/emoji/bundled/Android.mk
+++ b/emoji/bundled/Android.mk
@@ -28,7 +28,7 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := android-support-emoji-bundled
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
 LOCAL_SHARED_ANDROID_LIBRARIES := \
     android-support-annotations \
     android-support-emoji \
diff --git a/emoji/bundled/build.gradle b/emoji/bundled/build.gradle
index b882ee1..766d165 100644
--- a/emoji/bundled/build.gradle
+++ b/emoji/bundled/build.gradle
@@ -10,7 +10,6 @@
     }
 
     sourceSets {
-        main.java.srcDir 'src'
         main.assets.srcDirs new File(fontDir, "font").getAbsolutePath()
     }
 }
diff --git a/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java b/emoji/bundled/src/main/java/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
similarity index 100%
rename from emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
rename to emoji/bundled/src/main/java/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
diff --git a/emoji/core/Android.mk b/emoji/core/Android.mk
index 774ba29..8b7a032 100644
--- a/emoji/core/Android.mk
+++ b/emoji/core/Android.mk
@@ -27,8 +27,8 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := android-support-emoji
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
 LOCAL_STATIC_JAVA_LIBRARIES := \
     noto-emoji-compat-java
 LOCAL_SHARED_ANDROID_LIBRARIES := \
diff --git a/emoji/core/build.gradle b/emoji/core/build.gradle
index c0881d2..b4cd3fc 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -29,10 +29,7 @@
     }
 
     sourceSets {
-        main.java {
-            srcDirs = ['src']
-        }
-        main.res.srcDirs = ['res', 'res-public']
+        main.res.srcDirs += 'src/main/res-public'
         main.resources {
             srcDirs = [fontDir.getAbsolutePath()]
             includes = ["LICENSE_UNICODE", "LICENSE_OFL"]
diff --git a/emoji/core/src/android/support/text/emoji/EmojiCompat.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiCompat.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiMetadata.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiMetadata.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiProcessor.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiProcessor.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiSpan.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiSpan.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiSpan.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiSpan.java
diff --git a/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java b/emoji/core/src/main/java/android/support/text/emoji/FontRequestEmojiCompatConfig.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java
rename to emoji/core/src/main/java/android/support/text/emoji/FontRequestEmojiCompatConfig.java
diff --git a/emoji/core/src/android/support/text/emoji/MetadataListReader.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/MetadataListReader.java
rename to emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
diff --git a/emoji/core/src/android/support/text/emoji/MetadataRepo.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/MetadataRepo.java
rename to emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
diff --git a/emoji/core/src/android/support/text/emoji/TypefaceEmojiSpan.java b/emoji/core/src/main/java/android/support/text/emoji/TypefaceEmojiSpan.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/TypefaceEmojiSpan.java
rename to emoji/core/src/main/java/android/support/text/emoji/TypefaceEmojiSpan.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EditTextAttributeHelper.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EditTextAttributeHelper.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiButton.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiButton.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiButton.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiButton.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditText.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditText.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditText.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditText.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
similarity index 96%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
index edc511f..a999e34 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
@@ -20,6 +20,7 @@
 import android.os.Build;
 import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.text.emoji.EmojiCompat;
@@ -130,7 +131,8 @@
     /**
      * Updates the InputConnection with emoji support. Should be called from {@link
      * TextView#onCreateInputConnection(EditorInfo)}. When used on devices running API 18 or below,
-     * this method returns {@code inputConnection} that is given as a parameter.
+     * this method returns {@code inputConnection} that is given as a parameter. If
+     * {@code inputConnection} is {@code null}, returns {@code null}.
      *
      * @param inputConnection InputConnection instance created by TextView
      * @param outAttrs        EditorInfo passed into
@@ -138,10 +140,10 @@
      *
      * @return a new InputConnection instance that wraps {@code inputConnection}
      */
-    @NonNull
-    public InputConnection onCreateInputConnection(@NonNull final InputConnection inputConnection,
+    @Nullable
+    public InputConnection onCreateInputConnection(@Nullable final InputConnection inputConnection,
             @NonNull final EditorInfo outAttrs) {
-        Preconditions.checkNotNull(inputConnection, "inputConnection cannot be null");
+        if (inputConnection == null) return null;
         return mHelper.onCreateInputConnection(inputConnection, outAttrs);
     }
 
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditableFactory.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditableFactory.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiExtractEditText.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractEditText.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiExtractEditText.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractEditText.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiExtractTextLayout.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractTextLayout.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiExtractTextLayout.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractTextLayout.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiInputConnection.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputConnection.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiInputConnection.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputConnection.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputFilter.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputFilter.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiKeyListener.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiKeyListener.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiKeyListener.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiKeyListener.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextView.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextView.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextView.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextView.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextViewHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextViewHelper.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextViewHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextViewHelper.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextWatcher.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextWatcher.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTransformationMethod.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTransformationMethod.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/ExtractButtonCompat.java b/emoji/core/src/main/java/android/support/text/emoji/widget/ExtractButtonCompat.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/ExtractButtonCompat.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/ExtractButtonCompat.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/SpannableBuilder.java b/emoji/core/src/main/java/android/support/text/emoji/widget/SpannableBuilder.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/SpannableBuilder.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/SpannableBuilder.java
diff --git a/emoji/core/res-public/values/public_attrs.xml b/emoji/core/src/main/res-public/values/public_attrs.xml
similarity index 100%
rename from emoji/core/res-public/values/public_attrs.xml
rename to emoji/core/src/main/res-public/values/public_attrs.xml
diff --git a/emoji/core/res/layout/input_method_extract_view.xml b/emoji/core/src/main/res/layout/input_method_extract_view.xml
similarity index 100%
rename from emoji/core/res/layout/input_method_extract_view.xml
rename to emoji/core/src/main/res/layout/input_method_extract_view.xml
diff --git a/emoji/core/res/values/attrs.xml b/emoji/core/src/main/res/values/attrs.xml
similarity index 100%
rename from emoji/core/res/values/attrs.xml
rename to emoji/core/src/main/res/values/attrs.xml
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
index d2bd722..0756fa2 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
@@ -16,6 +16,7 @@
 
 package android.support.text.emoji.widget;
 
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
@@ -28,6 +29,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.text.TextWatcher;
 import android.text.method.KeyListener;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.EditText;
 
@@ -61,12 +63,28 @@
     public void testGetOnCreateInputConnection_returnsSameInputConnection() {
         final InputConnection param = mock(InputConnection.class);
         final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(param,
+                new EditorInfo());
+
+        assertSame(param, inputConnection);
+    }
+
+    @Test
+    public void testGetOnCreateInputConnection_withNullAttrs_returnsSameInputConnection() {
+        final InputConnection param = mock(InputConnection.class);
+        final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(param,
                 null);
 
         assertSame(param, inputConnection);
     }
 
     @Test
+    public void testGetOnCreateInputConnection_withNullInputConnection_returnsNull() {
+        final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(null,
+                new EditorInfo());
+        assertNull(inputConnection);
+    }
+
+    @Test
     public void testDoesNotAttachTextWatcher() {
         final EditText editText = mock(EditText.class);
 
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
index efc7ca0..626bca1 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
@@ -16,8 +16,11 @@
 
 package android.support.text.emoji.widget;
 
+import static junit.framework.Assert.assertNotNull;
+
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
@@ -32,6 +35,7 @@
 import android.support.text.emoji.EmojiCompat;
 import android.text.TextWatcher;
 import android.text.method.KeyListener;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.EditText;
 
@@ -76,16 +80,26 @@
         assertSame(keyListener1, keyListener2);
     }
 
-    @Test(expected = NullPointerException.class)
-    public void testGetOnCreateInputConnection_withNull_throwsException() {
-        mEmojiEditTextHelper.onCreateInputConnection(null, null);
+    @Test
+    public void testGetOnCreateInputConnection_withNullAttrs_returnsInputConnection() {
+        final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(
+                mock(InputConnection.class), null);
+        assertNotNull(inputConnection);
+        assertThat(inputConnection, instanceOf(EmojiInputConnection.class));
+    }
+
+    @Test
+    public void testGetOnCreateInputConnection_withNullInputConnection_returnsNull() {
+        InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(null,
+                new EditorInfo());
+        assertNull(inputConnection);
     }
 
     @Test
     public void testGetOnCreateInputConnection_returnsEmojiInputConnection() {
         final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(
                 mock(InputConnection.class), null);
-
+        assertNotNull(inputConnection);
         assertThat(inputConnection, instanceOf(EmojiInputConnection.class));
     }
 
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index ba74521..0eb7083 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -1371,7 +1371,7 @@
      * @param savedInstanceState If non-null, this fragment is being re-constructed
      * from a previous saved state as given here.
      */
-    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
     }
 
     /**
@@ -1469,7 +1469,7 @@
      *
      * @param outState Bundle in which to place your saved state.
      */
-    public void onSaveInstanceState(Bundle outState) {
+    public void onSaveInstanceState(@NonNull Bundle outState) {
     }
 
     /**
diff --git a/fragment/java/android/support/v4/app/FragmentActivity.java b/fragment/java/android/support/v4/app/FragmentActivity.java
index e513ff7..d6e446c 100644
--- a/fragment/java/android/support/v4/app/FragmentActivity.java
+++ b/fragment/java/android/support/v4/app/FragmentActivity.java
@@ -760,6 +760,7 @@
     @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
             @NonNull int[] grantResults) {
+        mFragments.noteStateNotSaved();
         int index = (requestCode >> 16) & 0xffff;
         if (index != 0) {
             index--;
diff --git a/fragment/java/android/support/v4/app/ListFragment.java b/fragment/java/android/support/v4/app/ListFragment.java
index 21617ad..496bd8e 100644
--- a/fragment/java/android/support/v4/app/ListFragment.java
+++ b/fragment/java/android/support/v4/app/ListFragment.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -142,7 +144,7 @@
      * Attach to list view once the view hierarchy has been created.
      */
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         ensureList();
     }
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index 241e99a..9d33e55 100644
--- a/lifecycle/extensions/build.gradle
+++ b/lifecycle/extensions/build.gradle
@@ -39,11 +39,11 @@
     }
 }
 dependencies {
-    compile project(":lifecycle:common")
     compile project(":lifecycle:runtime")
     compile project(":arch:common")
     compile project(":arch:runtime")
     compile libs.support.fragments, libs.support_exclude_config
+    compile project(":lifecycle:common")
 
     annotationProcessor project(":lifecycle:compiler")
 
diff --git a/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java b/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
index fe18243..1ddcb1a 100644
--- a/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
+++ b/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
@@ -16,7 +16,7 @@
 
 package android.arch.lifecycle;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.support.annotation.MainThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
@@ -53,7 +53,7 @@
             @Override
             protected void onActive() {
                 // TODO if we make this class public, we should accept an executor
-                AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+                ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
             }
         };
     }
@@ -115,7 +115,7 @@
             if (mInvalid.compareAndSet(false, true)) {
                 if (isActive) {
                     // TODO if we make this class public, we should accept an executor.
-                    AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+                    ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
                 }
             }
         }
@@ -127,7 +127,7 @@
      * When there are active observers, this will trigger a call to {@link #compute()}.
      */
     public void invalidate() {
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
+        ArchTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
     }
 
     @SuppressWarnings("WeakerAccess")
diff --git a/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java b/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
index 99d859c..da5600c 100644
--- a/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
+++ b/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
@@ -19,7 +19,7 @@
 import static android.arch.lifecycle.Lifecycle.State.DESTROYED;
 import static android.arch.lifecycle.Lifecycle.State.STARTED;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.internal.SafeIterableMap;
 import android.arch.lifecycle.Lifecycle.State;
 import android.support.annotation.MainThread;
@@ -197,7 +197,6 @@
             return;
         }
         owner.getLifecycle().addObserver(wrapper);
-        wrapper.activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
     }
 
     /**
@@ -274,7 +273,7 @@
         if (!postTask) {
             return;
         }
-        AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
+        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
     }
 
     /**
@@ -376,7 +375,6 @@
             // immediately set active state, so we'd never dispatch anything to inactive
             // owner
             activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
-
         }
 
         void activeStateChanged(boolean newActive) {
@@ -403,7 +401,7 @@
     }
 
     private void assertMainThread(String methodName) {
-        if (!AppToolkitTaskExecutor.getInstance().isMainThread()) {
+        if (!ArchTaskExecutor.getInstance().isMainThread()) {
             throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                     + " thread");
         }
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
index 0a3fbed..eb89d8d 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
@@ -27,7 +27,7 @@
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.arch.core.executor.TaskExecutorWithFakeMainThread;
 import android.arch.lifecycle.util.InstantTaskExecutor;
@@ -58,12 +58,12 @@
     @Before
     public void swapExecutorDelegate() {
         mTaskExecutor = spy(new InstantTaskExecutor());
-        AppToolkitTaskExecutor.getInstance().setDelegate(mTaskExecutor);
+        ArchTaskExecutor.getInstance().setDelegate(mTaskExecutor);
     }
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -76,7 +76,7 @@
     @Test
     public void noConcurrentCompute() throws InterruptedException {
         TaskExecutorWithFakeMainThread executor = new TaskExecutorWithFakeMainThread(2);
-        AppToolkitTaskExecutor.getInstance().setDelegate(executor);
+        ArchTaskExecutor.getInstance().setDelegate(executor);
         try {
             // # of compute calls
             final Semaphore computeCounter = new Semaphore(0);
@@ -121,7 +121,7 @@
             // assert no other results arrive
             verify(observer, never()).onChanged(anyInt());
         } finally {
-            AppToolkitTaskExecutor.getInstance().setDelegate(null);
+            ArchTaskExecutor.getInstance().setDelegate(null);
         }
     }
 
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
index ed2a35d..9f0b425 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
@@ -36,16 +36,20 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 import android.support.annotation.Nullable;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
 import org.mockito.Mockito;
 
 @SuppressWarnings({"unchecked"})
+@RunWith(JUnit4.class)
 public class LiveDataTest {
     private PublicLiveData<String> mLiveData;
     private LifecycleOwner mOwner;
@@ -66,12 +70,12 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -418,6 +422,40 @@
         verify(mActiveObserversChanged, never()).onCall(anyBoolean());
     }
 
+    @Test
+    public void testRemoveDuringAddition() {
+        mRegistry.handleLifecycleEvent(ON_START);
+        mLiveData.setValue("bla");
+        mLiveData.observeForever(new Observer<String>() {
+            @Override
+            public void onChanged(@Nullable String s) {
+                mLiveData.removeObserver(this);
+            }
+        });
+        assertThat(mLiveData.hasActiveObservers(), is(false));
+        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+        inOrder.verify(mActiveObserversChanged).onCall(true);
+        inOrder.verify(mActiveObserversChanged).onCall(false);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testRemoveDuringBringingUpToState() {
+        mLiveData.setValue("bla");
+        mLiveData.observeForever(new Observer<String>() {
+            @Override
+            public void onChanged(@Nullable String s) {
+                mLiveData.removeObserver(this);
+            }
+        });
+        mRegistry.handleLifecycleEvent(ON_RESUME);
+        assertThat(mLiveData.hasActiveObservers(), is(false));
+        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+        inOrder.verify(mActiveObserversChanged).onCall(true);
+        inOrder.verify(mActiveObserversChanged).onCall(false);
+        inOrder.verifyNoMoreInteractions();
+    }
+
     @SuppressWarnings("WeakerAccess")
     static class PublicLiveData<T> extends LiveData<T> {
         // cannot spy due to internal calls
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
index 3de3eee..e2eadbe 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 import android.support.annotation.Nullable;
 
@@ -69,7 +69,7 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @Test
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
index e92ecca..940a3e8 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.util.Function;
 import android.arch.lifecycle.util.InstantTaskExecutor;
 
@@ -42,7 +42,7 @@
 
     @Before
     public void swapExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
     }
 
     @Before
diff --git a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
index 0be0149..ec9b7f1 100644
--- a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
+++ b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
@@ -16,7 +16,7 @@
 
 package android.arch.lifecycle;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.support.annotation.Nullable;
 
 import org.reactivestreams.Publisher;
@@ -85,7 +85,7 @@
                         if (n < 0 || mCanceled) {
                             return;
                         }
-                        AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+                        ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
                             @Override
                             public void run() {
                                 if (mCanceled) {
@@ -110,7 +110,7 @@
                         if (mCanceled) {
                             return;
                         }
-                        AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+                        ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
                             @Override
                             public void run() {
                                 if (mCanceled) {
diff --git a/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java b/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
index 87fba27..ca52ee5 100644
--- a/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
+++ b/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
@@ -16,12 +16,10 @@
 
 package android.arch.lifecycle;
 
-import static android.arch.lifecycle.Lifecycle.State.RESUMED;
-
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.support.annotation.Nullable;
 import android.support.test.filters.SmallTest;
@@ -47,28 +45,7 @@
 
 @SmallTest
 public class LiveDataReactiveStreamsTest {
-    private static final Lifecycle sLifecycle = new Lifecycle() {
-        @Override
-        public void addObserver(LifecycleObserver observer) {
-        }
-
-        @Override
-        public void removeObserver(LifecycleObserver observer) {
-        }
-
-        @Override
-        public State getCurrentState() {
-            return RESUMED;
-        }
-    };
-    private static final LifecycleOwner S_LIFECYCLE_OWNER = new LifecycleOwner() {
-
-        @Override
-        public Lifecycle getLifecycle() {
-            return sLifecycle;
-        }
-
-    };
+    private LifecycleOwner mLifecycleOwner;
 
     private final List<String> mLiveDataOutput = new ArrayList<>();
     private final Observer<String> mObserver = new Observer<String>() {
@@ -85,8 +62,19 @@
 
     @Before
     public void init() {
+        mLifecycleOwner = new LifecycleOwner() {
+            LifecycleRegistry mRegistry = new LifecycleRegistry(this);
+            {
+                mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
+            }
+
+            @Override
+            public Lifecycle getLifecycle() {
+                return mRegistry;
+            }
+        };
         mTestThread = Thread.currentThread();
-        AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
 
             @Override
             public void executeOnDiskIO(Runnable runnable) {
@@ -109,7 +97,7 @@
 
     @After
     public void removeExecutorDelegate() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     @Test
@@ -117,7 +105,7 @@
         PublishProcessor<String> processor = PublishProcessor.create();
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         processor.onNext("foo");
         processor.onNext("bar");
@@ -132,13 +120,13 @@
         PublishProcessor<String> processor = PublishProcessor.create();
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         processor.onNext("foo");
         processor.onNext("bar");
 
         // The second mObserver should only get the newest value and any later values.
-        liveData.observe(S_LIFECYCLE_OWNER, new Observer<String>() {
+        liveData.observe(mLifecycleOwner, new Observer<String>() {
             @Override
             public void onChanged(@Nullable String s) {
                 output2.add(s);
@@ -157,7 +145,7 @@
                 .concatWith(Flowable.just("bar", "baz").observeOn(sBackgroundScheduler));
         LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(input);
 
-        liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+        liveData.observe(mLifecycleOwner, mObserver);
 
         assertThat(mLiveDataOutput, is(Collections.singletonList("foo")));
         sBackgroundScheduler.triggerActions();
@@ -170,7 +158,7 @@
         liveData.setValue("foo");
         assertThat(liveData.getValue(), is("foo"));
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(mOutputProcessor);
 
         liveData.setValue("bar");
@@ -188,7 +176,7 @@
         assertThat(liveData.getValue(), is("foo"));
 
         Disposable disposable = Flowable
-                .fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+                .fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(new Consumer<String>() {
                     @Override
                     public void accept(String s) throws Exception {
@@ -216,7 +204,7 @@
 
         final AsyncSubject<Subscription> subscriptionSubject = AsyncSubject.create();
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .subscribe(new Subscriber<String>() {
                     @Override
                     public void onSubscribe(Subscription s) {
@@ -275,7 +263,7 @@
     public void convertsToPublisherWithAsyncData() {
         MutableLiveData<String> liveData = new MutableLiveData<>();
 
-        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+        Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
                 .observeOn(sBackgroundScheduler)
                 .subscribe(mOutputProcessor);
 
diff --git a/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java b/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
index 1250aa1..07dd84b 100644
--- a/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
+++ b/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
@@ -16,7 +16,7 @@
 
 package android.arch.paging;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.ComputableLiveData;
 import android.arch.lifecycle.LiveData;
 import android.support.annotation.AnyThread;
@@ -134,9 +134,9 @@
 
                     mList = new PagedList.Builder<Key, Value>()
                             .setDataSource(mDataSource)
-                            .setMainThreadExecutor(AppToolkitTaskExecutor.getMainThreadExecutor())
+                            .setMainThreadExecutor(ArchTaskExecutor.getMainThreadExecutor())
                             .setBackgroundThreadExecutor(
-                                    AppToolkitTaskExecutor.getIOThreadExecutor())
+                                    ArchTaskExecutor.getIOThreadExecutor())
                             .setConfig(config)
                             .setInitialKey(initializeKey)
                             .build();
diff --git a/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java b/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
index f861242..25697a1 100644
--- a/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
+++ b/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
@@ -16,7 +16,7 @@
 
 package android.support.v7.recyclerview.extensions;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 
 import java.util.concurrent.Executor;
 
@@ -118,10 +118,10 @@
                 throw new IllegalArgumentException("Must provide a diffCallback");
             }
             if (mBackgroundThreadExecutor == null) {
-                mBackgroundThreadExecutor = AppToolkitTaskExecutor.getIOThreadExecutor();
+                mBackgroundThreadExecutor = ArchTaskExecutor.getIOThreadExecutor();
             }
             if (mMainThreadExecutor == null) {
-                mMainThreadExecutor = AppToolkitTaskExecutor.getMainThreadExecutor();
+                mMainThreadExecutor = ArchTaskExecutor.getMainThreadExecutor();
             }
             return new ListAdapterConfig<>(
                     mMainThreadExecutor,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
index 6dc71f6..daaa8e3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
@@ -84,7 +84,7 @@
 
 object ArchTypeNames {
     val APP_EXECUTOR : ClassName =
-            ClassName.get("android.arch.core.executor", "AppToolkitTaskExecutor")
+            ClassName.get("android.arch.core.executor", "ArchTaskExecutor")
 }
 
 object PagingTypeNames {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
index a4e8946..85e89d1 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
@@ -24,7 +24,6 @@
 import org.antlr.v4.runtime.Recognizer
 import org.antlr.v4.runtime.tree.ParseTree
 import org.antlr.v4.runtime.tree.TerminalNode
-import java.util.ArrayList
 import javax.annotation.processing.ProcessingEnvironment
 import javax.lang.model.type.TypeKind
 import javax.lang.model.type.TypeMirror
@@ -120,6 +119,7 @@
 
 class SqlParser {
     companion object {
+        private val INVALID_IDENTIFIER_CHARS = arrayOf('`', '\"')
         fun parse(input: String): ParsedQuery {
             val inputStream = ANTLRInputStream(input)
             val lexer = SQLiteLexer(inputStream)
@@ -153,6 +153,9 @@
                         listOf("unknown error while parsing $input : ${antlrError.message}"))
             }
         }
+
+        fun isValidIdentifier(input : String) : Boolean =
+                input.isNotBlank() && INVALID_IDENTIFIER_CHARS.none { input.contains(it) }
     }
 }
 
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
index cb8dd13..540c95a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
@@ -22,6 +22,7 @@
 import android.arch.persistence.room.ext.getAsStringList
 import android.arch.persistence.room.ext.toType
 import android.arch.persistence.room.parser.SQLTypeAffinity
+import android.arch.persistence.room.parser.SqlParser
 import android.arch.persistence.room.processor.ProcessorErrors.INDEX_COLUMNS_CANNOT_BE_EMPTY
 import android.arch.persistence.room.processor.ProcessorErrors.RELATION_IN_ENTITY
 import android.arch.persistence.room.processor.cache.Cache
@@ -127,6 +128,13 @@
         val entityForeignKeys = validateAndCreateForeignKeyReferences(foreignKeyInputs, pojo)
         checkIndicesForForeignKeys(entityForeignKeys, primaryKey, indices)
 
+        context.checker.check(SqlParser.isValidIdentifier(tableName), element,
+                ProcessorErrors.INVALID_TABLE_NAME)
+        pojo.fields.forEach {
+            context.checker.check(SqlParser.isValidIdentifier(it.columnName), it.element,
+                    ProcessorErrors.INVALID_COLUMN_NAME)
+        }
+
         val entity = Entity(element = element,
                 tableName = tableName,
                 type = pojo.type,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
index b1e8661..8058ff9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
@@ -17,7 +17,6 @@
 package android.arch.persistence.room.processor
 
 import android.arch.persistence.room.Delete
-import android.arch.persistence.room.Embedded
 import android.arch.persistence.room.Insert
 import android.arch.persistence.room.Query
 import android.arch.persistence.room.Update
@@ -200,6 +199,16 @@
                 """.trim()
     }
 
+    fun pojoMissingNonNull(pojoTypeName: TypeName, missingPojoFields: List<String>,
+                           allQueryColumns: List<String>) : String {
+        return """
+        The columns returned by the query does not have the fields
+        [${missingPojoFields.joinToString(",")}] in $pojoTypeName even though they are
+        annotated as non-null or primitive.
+        Columns returned by the query: [${allQueryColumns.joinToString(",")}]
+        """.trim()
+    }
+
     fun cursorPojoMismatch(pojoTypeName: TypeName,
                            unusedColumns: List<String>, allColumns: List<String>,
                            unusedFields: List<Field>, allFields: List<Field>): String {
@@ -459,4 +468,9 @@
                 "bug and Room does not allow it. See SQLite docs for details: " +
                 "https://www.sqlite.org/lang_createtable.html"
     }
+
+    val INVALID_COLUMN_NAME = "Invalid column name. Room does not allow using ` or \" in column" +
+            " names"
+
+    val INVALID_TABLE_NAME = "Invalid table name. Room does not allow using ` or \" in table names"
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
index 062b179..a013dc7 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
@@ -19,7 +19,6 @@
 import android.arch.persistence.room.ext.L
 import android.arch.persistence.room.ext.S
 import android.arch.persistence.room.ext.T
-import android.arch.persistence.room.ext.typeName
 import android.arch.persistence.room.processor.Context
 import android.arch.persistence.room.processor.ProcessorErrors
 import android.arch.persistence.room.solver.CodeGenScope
@@ -71,6 +70,13 @@
             )
             context.logger.w(Warning.CURSOR_MISMATCH, null, warningMsg)
         }
+        val nonNulls = remainingFields.filter { it.nonNull }
+        if (nonNulls.isNotEmpty()) {
+            context.logger.e(ProcessorErrors.pojoMissingNonNull(
+                    pojoTypeName = pojo.typeName,
+                    missingPojoFields = nonNulls.map { it.name },
+                    allQueryColumns = info.columns.map { it.name }))
+        }
         if (matchedFields.isEmpty()) {
             context.logger.e(ProcessorErrors.CANNOT_FIND_QUERY_RESULT_ADAPTER)
         }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
index 68b1868..6d3e194 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
@@ -63,6 +63,22 @@
     }
 
     @Test
+    fun validColumnNames() {
+        listOf("f", "fo", "f2", "f 2", "foo_2", "foo-2", "_", "foo bar baz",
+                "foo 2 baz", "_baz", "fooBar", "2", "*", "foo*2", "dsa$", "\$fsa",
+                "-bar", "ÅŸoöÄŸüı").forEach {
+            assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(true))
+        }
+    }
+
+    @Test
+    fun invalidColumnNames() {
+        listOf("", " ", "fd`a`", "f`a", "`a", "\"foo bar\"", "\"", "`").forEach {
+            assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(false))
+        }
+    }
+
+    @Test
     fun extractTableNames() {
         assertThat(SqlParser.parse("select * from users").tables,
                 `is`(setOf(Table("users", "users"))))
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
index 42fc3df..533d8c4 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
@@ -1775,7 +1775,47 @@
                     @Embedded
                     MyEntity myEntity;
                 }
-                """){ _, _ ->
+                """) { _, _ ->
         }.failsToCompile().withErrorContaining(ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format("foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
     }
+    fun okTableName() {
+        val annotation = mapOf("tableName" to "\"foo bar\"")
+        singleEntity(
+                """
+                @PrimaryKey
+                int id;
+                String name;
+                """,
+                attributes = annotation, jfos = listOf(COMMON.USER)
+        ){ _, _ ->
+        }.compilesWithoutError()
+    }
+
+    @Test
+    fun badTableName() {
+        val annotation = mapOf("tableName" to """ "foo`bar" """)
+        singleEntity(
+                """
+                @PrimaryKey
+                int id;
+                String name;
+                """,
+                attributes = annotation, jfos = listOf(COMMON.USER)
+        ){ _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_TABLE_NAME)
+    }
+
+    @Test
+    fun badColumnName() {
+        singleEntity(
+                """
+                @PrimaryKey
+                int id;
+                @ColumnInfo(name = "\"foo bar\"")
+                String name;
+                """,
+                jfos = listOf(COMMON.USER)
+        ){ _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_COLUMN_NAME)
+    }
 }
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
index 7e892b7..a2cb768 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
@@ -70,6 +70,7 @@
     companion object {
         const val DAO_PREFIX = """
                 package foo.bar;
+                import android.support.annotation.NonNull;
                 import android.arch.persistence.room.*;
                 @Dao
                 abstract class MyClass {
@@ -599,6 +600,30 @@
     }
 
     @Test
+    fun pojo_missingNonNull() {
+        pojoTest("""
+            @NonNull
+            String name;
+            String lastName;
+            """, listOf("lastName")) { adapter, _, _ ->
+            assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
+            assertThat(adapter?.mapping?.unusedFields, `is`(
+                    adapter?.pojo?.fields?.filter { it.name == "name" }
+            ))
+        }?.failsToCompile()?.withWarningContaining(
+                ProcessorErrors.cursorPojoMismatch(
+                        pojoTypeName = POJO,
+                        unusedColumns = emptyList(),
+                        unusedFields = listOf(createField("name")),
+                        allColumns = listOf("lastName"),
+                        allFields = listOf(createField("name"), createField("lastName"))
+                ))?.and()?.withErrorContaining(
+                ProcessorErrors.pojoMissingNonNull(pojoTypeName = POJO,
+                        missingPojoFields = listOf("name"),
+                        allQueryColumns = listOf("lastName")))
+    }
+
+    @Test
     fun pojo_tooManyFieldsAndColumns() {
         pojoTest("""
             String name;
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
index 9417296..2fad7b1 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
@@ -21,6 +21,7 @@
 import android.arch.persistence.room.TypeConverter;
 import android.arch.persistence.room.TypeConverters;
 import android.arch.persistence.room.integration.testapp.dao.BlobEntityDao;
+import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao;
 import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao;
 import android.arch.persistence.room.integration.testapp.dao.PetDao;
 import android.arch.persistence.room.integration.testapp.dao.ProductDao;
@@ -31,6 +32,7 @@
 import android.arch.persistence.room.integration.testapp.dao.UserPetDao;
 import android.arch.persistence.room.integration.testapp.dao.WithClauseDao;
 import android.arch.persistence.room.integration.testapp.vo.BlobEntity;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
 import android.arch.persistence.room.integration.testapp.vo.Pet;
 import android.arch.persistence.room.integration.testapp.vo.PetCouple;
 import android.arch.persistence.room.integration.testapp.vo.Product;
@@ -41,7 +43,7 @@
 import java.util.Date;
 
 @Database(entities = {User.class, Pet.class, School.class, PetCouple.class, Toy.class,
-        BlobEntity.class, Product.class},
+        BlobEntity.class, Product.class, FunnyNamedEntity.class},
         version = 1, exportSchema = false)
 @TypeConverters(TestDatabase.Converters.class)
 public abstract class TestDatabase extends RoomDatabase {
@@ -55,6 +57,7 @@
     public abstract ProductDao getProductDao();
     public abstract SpecificDogDao getSpecificDogDao();
     public abstract WithClauseDao getWithClauseDao();
+    public abstract FunnyNamedDao getFunnyNamedDao();
 
     @SuppressWarnings("unused")
     public static class Converters {
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java
new file mode 100644
index 0000000..93b5e72
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java
@@ -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.
+ */
+
+package android.arch.persistence.room.integration.testapp.dao;
+
+import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.COLUMN_ID;
+import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.TABLE_NAME;
+
+import android.arch.lifecycle.LiveData;
+import android.arch.persistence.room.Dao;
+import android.arch.persistence.room.Delete;
+import android.arch.persistence.room.Insert;
+import android.arch.persistence.room.Query;
+import android.arch.persistence.room.Update;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
+
+import java.util.List;
+
+@Dao
+public interface FunnyNamedDao {
+    String SELECT_ONE = "select * from \"" +  TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" = :id";
+    @Insert
+    void insert(FunnyNamedEntity... entities);
+    @Delete
+    void delete(FunnyNamedEntity... entities);
+    @Update
+    void update(FunnyNamedEntity... entities);
+
+    @Query("select * from \"" +  TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" IN (:ids)")
+    List<FunnyNamedEntity> loadAll(int... ids);
+
+    @Query(SELECT_ONE)
+    LiveData<FunnyNamedEntity> observableOne(int id);
+
+    @Query(SELECT_ONE)
+    FunnyNamedEntity load(int id);
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
index 7bb137f..18e8d93 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
@@ -35,16 +35,16 @@
     @Query("SELECT * from School WHERE address_street LIKE '%' || :street || '%'")
     public abstract List<School> findByStreet(String street);
 
-    @Query("SELECT mName, manager_mName FROM School")
+    @Query("SELECT mId, mName, manager_mName FROM School")
     public abstract List<School> schoolAndManagerNames();
 
-    @Query("SELECT mName, manager_mName FROM School")
+    @Query("SELECT mId, mName, manager_mName FROM School")
     @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
     public abstract List<SchoolRef> schoolAndManagerNamesAsPojo();
 
     @Query("SELECT address_lat as lat, address_lng as lng FROM School WHERE mId = :schoolId")
     public abstract Coordinates loadCoordinates(int schoolId);
 
-    @Query("SELECT address_lat, address_lng FROM School WHERE mId = :schoolId")
+    @Query("SELECT mId, address_lat, address_lng FROM School WHERE mId = :schoolId")
     public abstract School loadCoordinatesAsSchool(int schoolId);
 }
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
index 4c9d73e..df70a17 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
@@ -21,17 +21,17 @@
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.testing.CountingTaskExecutorRule;
 import android.arch.lifecycle.Lifecycle;
 import android.arch.lifecycle.LifecycleOwner;
 import android.arch.lifecycle.LifecycleRegistry;
 import android.arch.lifecycle.LiveData;
 import android.arch.lifecycle.Observer;
+import android.arch.paging.PagedList;
 import android.arch.persistence.room.integration.testapp.test.TestDatabaseTest;
 import android.arch.persistence.room.integration.testapp.test.TestUtil;
 import android.arch.persistence.room.integration.testapp.vo.User;
-import android.arch.paging.PagedList;
 import android.support.annotation.Nullable;
 import android.support.test.filters.LargeTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -131,7 +131,7 @@
                 return null;
             }
         });
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask);
+        ArchTaskExecutor.getInstance().executeOnMainThread(futureTask);
         futureTask.get();
     }
 
@@ -155,7 +155,7 @@
 
     private static class PagedListObserver<T> implements Observer<PagedList<T>> {
         private PagedList<T> mList;
-        public void reset() {
+        void reset() {
             mList = null;
         }
 
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java
new file mode 100644
index 0000000..f4fca7f
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.arch.persistence.room.integration.testapp.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.arch.core.executor.testing.CountingTaskExecutorRule;
+import android.arch.lifecycle.Observer;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
+import android.support.annotation.Nullable;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class FunnyNamedDaoTest extends TestDatabaseTest {
+    @Rule
+    public CountingTaskExecutorRule mExecutorRule = new CountingTaskExecutorRule();
+
+    @Test
+    public void readWrite() {
+        FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+        mFunnyNamedDao.insert(entity);
+        FunnyNamedEntity loaded = mFunnyNamedDao.load(1);
+        assertThat(loaded, is(entity));
+    }
+
+    @Test
+    public void update() {
+        FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+        mFunnyNamedDao.insert(entity);
+        entity.setValue("b");
+        mFunnyNamedDao.update(entity);
+        FunnyNamedEntity loaded = mFunnyNamedDao.load(1);
+        assertThat(loaded.getValue(), is("b"));
+    }
+
+    @Test
+    public void delete() {
+        FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+        mFunnyNamedDao.insert(entity);
+        assertThat(mFunnyNamedDao.load(1), notNullValue());
+        mFunnyNamedDao.delete(entity);
+        assertThat(mFunnyNamedDao.load(1), nullValue());
+    }
+
+    @Test
+    public void observe() throws TimeoutException, InterruptedException {
+        final FunnyNamedEntity[] item = new FunnyNamedEntity[1];
+        mFunnyNamedDao.observableOne(2).observeForever(new Observer<FunnyNamedEntity>() {
+            @Override
+            public void onChanged(@Nullable FunnyNamedEntity funnyNamedEntity) {
+                item[0] = funnyNamedEntity;
+            }
+        });
+
+        FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+        mFunnyNamedDao.insert(entity);
+        mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+        assertThat(item[0], nullValue());
+
+        final FunnyNamedEntity entity2 = new FunnyNamedEntity(2, "b");
+        mFunnyNamedDao.insert(entity2);
+        mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+        assertThat(item[0], is(entity2));
+
+        final FunnyNamedEntity entity3 = new FunnyNamedEntity(2, "c");
+        mFunnyNamedDao.update(entity3);
+        mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+        assertThat(item[0], is(entity3));
+    }
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
index 4787ce5..84f20ec 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
@@ -21,7 +21,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.arch.persistence.room.InvalidationTracker;
 import android.arch.persistence.room.Room;
@@ -68,7 +68,7 @@
 
     @Before
     public void setSingleThreadedIO() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
             ExecutorService mIOExecutor = Executors.newSingleThreadExecutor();
             Handler mHandler = new Handler(Looper.getMainLooper());
 
@@ -91,7 +91,7 @@
 
     @After
     public void clearExecutor() {
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     private void waitUntilIOThreadIsIdle() {
@@ -101,7 +101,7 @@
                 return null;
             }
         });
-        AppToolkitTaskExecutor.getInstance().executeOnDiskIO(future);
+        ArchTaskExecutor.getInstance().executeOnDiskIO(future);
         //noinspection TryWithIdenticalCatches
         try {
             future.get();
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
index cae8445..b1f6851 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
@@ -21,7 +21,7 @@
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.testing.CountingTaskExecutorRule;
 import android.arch.lifecycle.Lifecycle;
 import android.arch.lifecycle.LifecycleOwner;
@@ -322,7 +322,7 @@
                 return null;
             }
         });
-        AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask);
+        ArchTaskExecutor.getInstance().executeOnMainThread(futureTask);
         futureTask.get();
     }
 
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
index 98783f2..01d071e 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
@@ -19,7 +19,7 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.arch.persistence.room.EmptyResultSetException;
 import android.arch.persistence.room.integration.testapp.vo.Pet;
@@ -55,7 +55,7 @@
     public void setupSchedulers() {
         mTestScheduler = new TestScheduler();
         mTestScheduler.start();
-        AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
             @Override
             public void executeOnDiskIO(Runnable runnable) {
                 mTestScheduler.scheduleDirect(runnable);
@@ -76,7 +76,7 @@
     @After
     public void clearSchedulers() {
         mTestScheduler.shutdown();
-        AppToolkitTaskExecutor.getInstance().setDelegate(null);
+        ArchTaskExecutor.getInstance().setDelegate(null);
     }
 
     private void drain() throws InterruptedException {
@@ -305,4 +305,27 @@
             }
         });
     }
+
+    @Test
+    public void flowable_updateInTransaction() throws InterruptedException {
+        // When subscribing to the emissions of the user
+        final TestSubscriber<User> userTestSubscriber = mUserDao
+                .flowableUserById(3)
+                .observeOn(mTestScheduler)
+                .test();
+        drain();
+        userTestSubscriber.assertValueCount(0);
+
+        // When inserting a new user in the data source
+        mDatabase.beginTransaction();
+        try {
+            mUserDao.insert(TestUtil.createUser(3));
+            mDatabase.setTransactionSuccessful();
+
+        } finally {
+            mDatabase.endTransaction();
+        }
+        drain();
+        userTestSubscriber.assertValueCount(1);
+    }
 }
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
new file mode 100644
index 0000000..fcd0b00
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.arch.persistence.room.integration.testapp.test;
+
+import android.arch.core.executor.testing.InstantTaskExecutorRule;
+import android.arch.persistence.room.Room;
+import android.arch.persistence.room.integration.testapp.TestDatabase;
+import android.arch.persistence.room.integration.testapp.vo.User;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import io.reactivex.subscribers.TestSubscriber;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RxJava2WithInstantTaskExecutorTest {
+    @Rule
+    public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
+
+    private TestDatabase mDatabase;
+
+    @Before
+    public void initDb() throws Exception {
+        // using an in-memory database because the information stored here disappears when the
+        // process is killed
+        mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
+                TestDatabase.class)
+                // allowing main thread queries, just for testing
+                .allowMainThreadQueries()
+                .build();
+    }
+
+    @Test
+    public void testFlowableInTransaction() {
+        // When subscribing to the emissions of the user
+        TestSubscriber<User> subscriber = mDatabase.getUserDao().flowableUserById(3).test();
+        subscriber.assertValueCount(0);
+
+        // When inserting a new user in the data source
+        mDatabase.beginTransaction();
+        try {
+            mDatabase.getUserDao().insert(TestUtil.createUser(3));
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        subscriber.assertValueCount(1);
+    }
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
index 51d5bb3..ec77561 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
@@ -18,6 +18,7 @@
 
 import android.arch.persistence.room.Room;
 import android.arch.persistence.room.integration.testapp.TestDatabase;
+import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao;
 import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao;
 import android.arch.persistence.room.integration.testapp.dao.PetDao;
 import android.arch.persistence.room.integration.testapp.dao.SchoolDao;
@@ -42,6 +43,7 @@
     protected ToyDao mToyDao;
     protected SpecificDogDao mSpecificDogDao;
     protected WithClauseDao mWithClauseDao;
+    protected FunnyNamedDao mFunnyNamedDao;
 
     @Before
     public void createDb() {
@@ -55,5 +57,6 @@
         mToyDao = mDatabase.getToyDao();
         mSpecificDogDao = mDatabase.getSpecificDogDao();
         mWithClauseDao = mDatabase.getWithClauseDao();
+        mFunnyNamedDao = mDatabase.getFunnyNamedDao();
     }
 }
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java
new file mode 100644
index 0000000..20f3c21
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java
@@ -0,0 +1,75 @@
+/*
+ * 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.arch.persistence.room.integration.testapp.vo;
+
+import android.arch.persistence.room.ColumnInfo;
+import android.arch.persistence.room.Entity;
+import android.arch.persistence.room.PrimaryKey;
+
+/**
+ * An entity that was weird names
+ */
+@Entity(tableName = FunnyNamedEntity.TABLE_NAME)
+public class FunnyNamedEntity {
+    public static final String TABLE_NAME = "funny but not so funny";
+    public static final String COLUMN_ID = "_this $is id$";
+    public static final String COLUMN_VALUE = "unlikely-ΩÅŸå¨Ä±ünames";
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = COLUMN_ID)
+    private int mId;
+    @ColumnInfo(name = COLUMN_VALUE)
+    private String mValue;
+
+    public FunnyNamedEntity(int id, String value) {
+        mId = id;
+        mValue = value;
+    }
+
+    public int getId() {
+        return mId;
+    }
+
+    public void setId(int id) {
+        mId = id;
+    }
+
+    public String getValue() {
+        return mValue;
+    }
+
+    public void setValue(String value) {
+        mValue = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        FunnyNamedEntity entity = (FunnyNamedEntity) o;
+
+        if (mId != entity.mId) return false;
+        return mValue != null ? mValue.equals(entity.mValue) : entity.mValue == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mId;
+        result = 31 * result + (mValue != null ? mValue.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
index 1f434ad..320b2cd 100644
--- a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
+++ b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
@@ -17,7 +17,7 @@
 package android.arch.persistence.room.integration.testapp;
 
 import android.app.Application;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.lifecycle.AndroidViewModel;
 import android.arch.lifecycle.LiveData;
 import android.arch.paging.DataSource;
@@ -47,7 +47,7 @@
         mDatabase = Room.databaseBuilder(this.getApplication(),
                 SampleDatabase.class, "customerDatabase").build();
 
-        AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
+        ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
             @Override
             public void run() {
                 // fill with some simple data
@@ -73,7 +73,7 @@
     }
 
     void insertCustomer() {
-        AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
+        ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
             @Override
             public void run() {
                 mDatabase.getCustomerDao().insert(createCustomer());
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java b/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
index 33bc4ed..45ec028 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
@@ -16,7 +16,7 @@
 
 package android.arch.persistence.room;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.core.internal.SafeIterableMap;
 import android.arch.persistence.db.SupportSQLiteDatabase;
 import android.arch.persistence.db.SupportSQLiteStatement;
@@ -166,10 +166,12 @@
 
     private static void appendTriggerName(StringBuilder builder, String tableName,
             String triggerType) {
-        builder.append("room_table_modification_trigger_")
+        builder.append("`")
+                .append("room_table_modification_trigger_")
                 .append(tableName)
                 .append("_")
-                .append(triggerType);
+                .append(triggerType)
+                .append("`");
     }
 
     private void stopTrackingTable(SupportSQLiteDatabase writableDb, int tableId) {
@@ -192,9 +194,9 @@
             appendTriggerName(stringBuilder, tableName, trigger);
             stringBuilder.append(" AFTER ")
                     .append(trigger)
-                    .append(" ON ")
+                    .append(" ON `")
                     .append(tableName)
-                    .append(" BEGIN INSERT OR REPLACE INTO ")
+                    .append("` BEGIN INSERT OR REPLACE INTO ")
                     .append(UPDATE_TABLE_NAME)
                     .append(" VALUES(null, ")
                     .append(tableId)
@@ -238,7 +240,7 @@
             currentObserver = mObserverMap.putIfAbsent(observer, wrapper);
         }
         if (currentObserver == null && mObservedTableTracker.onAdded(tableIds)) {
-            AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
+            ArchTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
         }
     }
 
@@ -269,7 +271,7 @@
             wrapper = mObserverMap.remove(observer);
         }
         if (wrapper != null && mObservedTableTracker.onRemoved(wrapper.mTableIds)) {
-            AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
+            ArchTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
         }
     }
 
@@ -350,11 +352,18 @@
                     return;
                 }
 
-                if (mDatabase.inTransaction()
-                        || !mPendingRefresh.compareAndSet(true, false)) {
+                if (!mPendingRefresh.compareAndSet(true, false)) {
                     // no pending refresh
                     return;
                 }
+
+                if (mDatabase.inTransaction()) {
+                    // current thread is in a transaction. when it ends, it will invoke
+                    // refreshRunnable again. mPendingRefresh is left as false on purpose
+                    // so that the last transaction can flip it on again.
+                    return;
+                }
+
                 mCleanupStatement.executeUpdateDelete();
                 mQueryArgs[0] = mMaxVersion;
                 Cursor cursor = mDatabase.query(SELECT_UPDATED_TABLES_SQL, mQueryArgs);
@@ -400,7 +409,7 @@
     public void refreshVersionsAsync() {
         // TODO we should consider doing this sync instead of async.
         if (mPendingRefresh.compareAndSet(false, true)) {
-            AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+            ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
         }
     }
 
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
index d6a7f8e..cdad868 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
@@ -16,7 +16,7 @@
 
 package android.arch.persistence.room;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.arch.persistence.db.SimpleSQLiteQuery;
 import android.arch.persistence.db.SupportSQLiteDatabase;
 import android.arch.persistence.db.SupportSQLiteOpenHelper;
@@ -158,7 +158,7 @@
         if (mAllowMainThreadQueries) {
             return;
         }
-        if (AppToolkitTaskExecutor.getInstance().isMainThread()) {
+        if (ArchTaskExecutor.getInstance().isMainThread()) {
             throw new IllegalStateException("Cannot access database on the main thread since"
                     + " it may potentially lock the UI for a long period of time.");
         }
@@ -216,7 +216,11 @@
      */
     public void endTransaction() {
         mOpenHelper.getWritableDatabase().endTransaction();
-        mInvalidationTracker.refreshVersionsAsync();
+        if (!inTransaction()) {
+            // enqueue refresh only if we are NOT in a transaction. Otherwise, wait for the last
+            // endTransaction call to do it.
+            mInvalidationTracker.refreshVersionsAsync();
+        }
     }
 
     /**
diff --git a/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java b/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
index adfca27..285b3f8 100644
--- a/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
+++ b/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
@@ -16,7 +16,7 @@
 
 package android.arch.persistence.room;
 
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 
@@ -133,7 +133,7 @@
                 public Disposable schedule(@NonNull Runnable run, long delay,
                         @NonNull TimeUnit unit) {
                     DisposableRunnable disposable = new DisposableRunnable(run, mDisposed);
-                    AppToolkitTaskExecutor.getInstance().executeOnDiskIO(run);
+                    ArchTaskExecutor.getInstance().executeOnDiskIO(run);
                     return disposable;
                 }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
index 7431da7..dba78da 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
@@ -14,6 +14,8 @@
 package android.support.v17.leanback.app;
 
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.widget.ItemBridgeAdapter;
 import android.support.v17.leanback.widget.ListRow;
 import android.support.v17.leanback.widget.ObjectAdapter;
@@ -75,7 +77,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         if (savedInstanceState != null) {
             mSelectedPosition = savedInstanceState.getInt(CURRENT_SELECTED_POSITION, -1);
         }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
index 177052d..d89cf39 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
@@ -15,6 +15,8 @@
 
 import android.annotation.SuppressLint;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.transition.TransitionHelper;
 import android.support.v17.leanback.transition.TransitionListener;
 import android.support.v17.leanback.util.StateMachine;
@@ -177,7 +179,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mStateMachine.fireEvent(EVT_ON_CREATEVIEW);
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
index aff8c89..306e1f1 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
@@ -15,6 +15,8 @@
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.SearchOrbView;
 import android.support.v17.leanback.widget.TitleHelper;
@@ -143,7 +145,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         if (savedInstanceState != null) {
             mShowingTitle = savedInstanceState.getBoolean(TITLE_SHOW);
diff --git a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
index 7a45630..56c85af 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
@@ -20,6 +20,8 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.support.v17.leanback.widget.DividerPresenter;
@@ -160,7 +162,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         final VerticalGridView listView = getVerticalGridView();
         if (listView == null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
index 9892625..51cb2de 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
@@ -26,6 +26,7 @@
 import android.graphics.Color;
 import android.os.Bundle;
 import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.PagingIndicator;
@@ -350,7 +351,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         if (savedInstanceState == null) {
             mCurrentPageIndex = 0;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
index 197e275..a8741ab 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
@@ -24,6 +24,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.animation.LogAccelerateInterpolator;
 import android.support.v17.leanback.animation.LogDecelerateInterpolator;
@@ -447,7 +449,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         // controls view are initially visible, make it invisible
         // if app has called hideControlsOverlay() before view created.
diff --git a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
index dd357ac..05e3813 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
@@ -16,6 +16,8 @@
 import android.animation.TimeAnimator;
 import android.animation.TimeAnimator.TimeListener;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
 import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
@@ -285,7 +287,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         if (DEBUG) Log.v(TAG, "onViewCreated");
         super.onViewCreated(view, savedInstanceState);
         // Align the top edge of child with id row_content.
diff --git a/v17/leanback/src/android/support/v17/leanback/app/package-info.java b/v17/leanback/src/android/support/v17/leanback/app/package-info.java
index f82570e..b736909 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/package-info.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/package-info.java
@@ -15,37 +15,37 @@
 /**
  * <p>Support classes providing high level Leanback user interface building blocks.</p>
  * <p>
- * Leanback fragments are available both as platform fragments (subclassed from
- * {@link android.app.Fragment android.app.Fragment}) and as support fragments (subclassed from
- * {@link android.support.v4.app.Fragment android.support.v4.app.Fragment}).  A few of the most
+ * Leanback fragments are available both as support fragments (subclassed from
+ * {@link android.support.v4.app.Fragment android.support.v4.app.Fragment}) and as platform
+ * fragments (subclassed from {@link android.app.Fragment android.app.Fragment}). A few of the most
  * commonly used leanback fragments are described here.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.BrowseFragment} by default operates in the "row" mode.
- * It includes an optional “fastlane”
+ * A {@link android.support.v17.leanback.app.BrowseSupportFragment} by default operates in the "row"
+ * mode. It includes an optional “fastlane”
  * navigation side panel and a list of rows, with one-to-one correspondance between each header
  * in the fastlane and a row.  The application supplies the
  * {@link android.support.v17.leanback.widget.ObjectAdapter} containing the list of
  * rows and a {@link android.support.v17.leanback.widget.PresenterSelector} of row presenters.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.BrowseFragment} also works in a "page" mode when
+ * A {@link android.support.v17.leanback.app.BrowseSupportFragment} also works in a "page" mode when
  * each row of fastlane is mapped to a fragment that the app registers in
- * {@link android.support.v17.leanback.app.BrowseFragment#getMainFragmentRegistry()}.
+ * {@link android.support.v17.leanback.app.BrowseSupportFragment#getMainFragmentRegistry()}.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.DetailsFragment} will typically consist of a large
- * overview of an item at the top,
+ * A {@link android.support.v17.leanback.app.DetailsSupportFragment} will typically consist of a
+ * large overview of an item at the top,
  * some actions that a user can perform, and possibly rows of additional or related items.
- * The content for this fragment is specified in the same way as for the BrowseFragment, with the
- * convention that the first element in the ObjectAdapter corresponds to the overview row.
+ * The content for this fragment is specified in the same way as for the BrowseSupportFragment, with
+ * the convention that the first element in the ObjectAdapter corresponds to the overview row.
  * The {@link android.support.v17.leanback.widget.DetailsOverviewRow} and
  * {@link android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter} provide a
  * default template for this row.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.PlaybackFragment} or its subclass
- * {@link android.support.v17.leanback.app.VideoFragment} hosts
+ * A {@link android.support.v17.leanback.app.PlaybackSupportFragment} or its subclass
+ * {@link android.support.v17.leanback.app.VideoSupportFragment} hosts
  * {@link android.support.v17.leanback.media.PlaybackTransportControlGlue}
  * or {@link android.support.v17.leanback.media.PlaybackBannerControlGlue} with a Leanback
  * look and feel.  It is recommended to use an instance of
@@ -54,13 +54,13 @@
  * the most commonly used controls as well as video scrubbing.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.SearchFragment} allows the developer to accept a query
- * from a user and display the results
+ * A {@link android.support.v17.leanback.app.SearchSupportFragment} allows the developer to accept a
+ * query from a user and display the results
  * using the familiar list rows.
  * </p>
  * <p>
- * A {@link android.support.v17.leanback.app.GuidedStepFragment} is used to guide the user through a
- * decision or series of decisions.
+ * A {@link android.support.v17.leanback.app.GuidedStepSupportFragment} is used to guide the user
+ * through a decision or series of decisions.
  * </p>
  **/
 
diff --git a/v17/leanback/src/android/support/v17/leanback/package-info.java b/v17/leanback/src/android/support/v17/leanback/package-info.java
index 5259f63..80b26e9 100644
--- a/v17/leanback/src/android/support/v17/leanback/package-info.java
+++ b/v17/leanback/src/android/support/v17/leanback/package-info.java
@@ -41,13 +41,13 @@
  * <p>
  * Leanback contains a mixture of higher level building blocks such as Fragments in the
  * {@link android.support.v17.leanback.app} package. Notable examples are the
- * {@link android.support.v17.leanback.app.BrowseFragment},
- * {@link android.support.v17.leanback.app.DetailsFragment},
- * {@link android.support.v17.leanback.app.PlaybackFragment} and the
- * {@link android.support.v17.leanback.app.GuidedStepFragment}.  Helper classes are also provided
- * that work with the leanback fragments, for example the
+ * {@link android.support.v17.leanback.app.BrowseSupportFragment},
+ * {@link android.support.v17.leanback.app.DetailsSupportFragment},
+ * {@link android.support.v17.leanback.app.PlaybackSupportFragment} and the
+ * {@link android.support.v17.leanback.app.GuidedStepSupportFragment}.  Helper classes are also
+ * provided that work with the leanback fragments, for example the
  * {@link android.support.v17.leanback.media.PlaybackTransportControlGlue} and
- * {@link android.support.v17.leanback.app.PlaybackFragmentGlueHost}.
+ * {@link android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost}.
  * </p>
  * <p>
  * Many lower level building blocks are also provided in the {@link android.support.v17.leanback.widget} package.
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
index 4fb9ff8..0e7fb8f 100644
--- a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
+++ b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
@@ -321,7 +321,7 @@
     }
 
     @Override
-    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         if (mHavePrefs) {
diff --git a/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java b/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
index b0a2cb3..aee48df 100644
--- a/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
+++ b/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
@@ -292,6 +292,11 @@
      */
     GestureDetectorCompat mGestureDetector;
 
+    /**
+     * Callback for when long press occurs.
+     */
+    private ItemTouchHelperGestureListener mItemTouchHelperGestureListener;
+
     private final OnItemTouchListener mOnItemTouchListener = new OnItemTouchListener() {
         @Override
         public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
@@ -468,7 +473,7 @@
         mRecyclerView.addItemDecoration(this);
         mRecyclerView.addOnItemTouchListener(mOnItemTouchListener);
         mRecyclerView.addOnChildAttachStateChangeListener(this);
-        initGestureDetector();
+        startGestureDetection();
     }
 
     private void destroyCallbacks() {
@@ -485,14 +490,23 @@
         mOverdrawChild = null;
         mOverdrawChildPosition = -1;
         releaseVelocityTracker();
+        stopGestureDetection();
     }
 
-    private void initGestureDetector() {
-        if (mGestureDetector != null) {
-            return;
-        }
+    private void startGestureDetection() {
+        mItemTouchHelperGestureListener = new ItemTouchHelperGestureListener();
         mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),
-                new ItemTouchHelperGestureListener());
+                mItemTouchHelperGestureListener);
+    }
+
+    private void stopGestureDetection() {
+        if (mItemTouchHelperGestureListener != null) {
+            mItemTouchHelperGestureListener.doNotReactToLongPress();
+            mItemTouchHelperGestureListener = null;
+        }
+        if (mGestureDetector != null) {
+            mGestureDetector = null;
+        }
     }
 
     private void getSelectedDxDy(float[] outPosition) {
@@ -2242,9 +2256,33 @@
 
     private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
 
+        /**
+         * Whether to execute code in response to the the invoking of
+         * {@link ItemTouchHelperGestureListener#onLongPress(MotionEvent)}.
+         *
+         * It is necessary to control this here because
+         * {@link GestureDetector.SimpleOnGestureListener} can only be set on a
+         * {@link GestureDetector} in a GestureDetector's constructor, a GestureDetector will call
+         * onLongPress if an {@link MotionEvent#ACTION_DOWN} event is not followed by another event
+         * that would cancel it (like {@link MotionEvent#ACTION_UP} or
+         * {@link MotionEvent#ACTION_CANCEL}), the long press responding to the long press event
+         * needs to be cancellable to prevent unexpected behavior.
+         *
+         * @see #doNotReactToLongPress()
+         */
+        private boolean mShouldReactToLongPress = true;
+
         ItemTouchHelperGestureListener() {
         }
 
+        /**
+         * Call to prevent executing code in response to
+         * {@link ItemTouchHelperGestureListener#onLongPress(MotionEvent)} being called.
+         */
+        void doNotReactToLongPress() {
+            mShouldReactToLongPress = false;
+        }
+
         @Override
         public boolean onDown(MotionEvent e) {
             return true;
@@ -2252,6 +2290,9 @@
 
         @Override
         public void onLongPress(MotionEvent e) {
+            if (!mShouldReactToLongPress) {
+                return;
+            }
             View child = findChildView(e);
             if (child != null) {
                 ViewHolder vh = mRecyclerView.getChildViewHolder(child);
diff --git a/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java b/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
index 02099ba..1a64e3c 100644
--- a/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
+++ b/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
@@ -142,13 +142,6 @@
         inst.sendPointerSync(event);
         inst.waitForIdleSync();
 
-        eventTime = SystemClock.uptimeMillis();
-        final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
-        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
-                x + touchSlop / 2, y + touchSlop / 2, 0);
-        inst.sendPointerSync(event);
-        inst.waitForIdleSync();
-
         try {
             Thread.sleep((long) (ViewConfiguration.getLongPressTimeout() * 1.5f));
         } catch (InterruptedException e) {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
index 18af47b..090ea69 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
@@ -32,11 +32,13 @@
 import android.support.test.filters.Suppress;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.testutils.PollingCheck;
+import android.support.v4.util.Pair;
 import android.support.v7.util.TouchUtils;
 import android.support.v7.widget.BaseRecyclerViewInstrumentationTest;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.WrappedRecyclerView;
 import android.view.Gravity;
+import android.view.View;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -48,26 +50,27 @@
 @RunWith(AndroidJUnit4.class)
 public class ItemTouchHelperTest extends BaseRecyclerViewInstrumentationTest {
 
-    TestAdapter mAdapter;
-
-    TestLayoutManager mLayoutManager;
+    private static class RecyclerViewState {
+        public TestAdapter mAdapter;
+        public TestLayoutManager mLayoutManager;
+        public WrappedRecyclerView mWrappedRecyclerView;
+    }
 
     private LoggingCalback mCalback;
 
     private LoggingItemTouchHelper mItemTouchHelper;
 
-    private WrappedRecyclerView mWrappedRecyclerView;
-
     private Boolean mSetupRTL;
 
     public ItemTouchHelperTest() {
         super(false);
     }
 
-    private RecyclerView setup(int dragDirs, int swipeDirs) throws Throwable {
-        mWrappedRecyclerView = inflateWrappedRV();
-        mAdapter = new TestAdapter(10);
-        mLayoutManager = new TestLayoutManager() {
+    private RecyclerViewState setupRecyclerView() throws Throwable {
+        RecyclerViewState rvs = new RecyclerViewState();
+        rvs.mWrappedRecyclerView = inflateWrappedRV();
+        rvs.mAdapter = new TestAdapter(10);
+        rvs.mLayoutManager = new TestLayoutManager() {
             @Override
             public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
                 detachAndScrapAttachedViews(recycler);
@@ -85,19 +88,24 @@
                 return false;
             }
         };
-        mWrappedRecyclerView.setFakeRTL(mSetupRTL);
-        mWrappedRecyclerView.setAdapter(mAdapter);
-        mWrappedRecyclerView.setLayoutManager(mLayoutManager);
+        rvs.mWrappedRecyclerView.setFakeRTL(mSetupRTL);
+        rvs.mWrappedRecyclerView.setAdapter(rvs.mAdapter);
+        rvs.mWrappedRecyclerView.setLayoutManager(rvs.mLayoutManager);
+        return rvs;
+    }
+
+    private RecyclerViewState setupItemTouchHelper(final RecyclerViewState rvs, int dragDirs,
+            int swipeDirs) throws Throwable {
         mCalback = new LoggingCalback(dragDirs, swipeDirs);
         mItemTouchHelper = new LoggingItemTouchHelper(mCalback);
         mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mItemTouchHelper.attachToRecyclerView(mWrappedRecyclerView);
+                mItemTouchHelper.attachToRecyclerView(rvs.mWrappedRecyclerView);
             }
         });
 
-        return mWrappedRecyclerView;
+        return rvs;
     }
 
     @Test
@@ -136,11 +144,60 @@
         basicSwipeTest(END, START | END, -getActivity().getWindow().getDecorView().getWidth());
     }
 
+    @Test
+    public void attachToNullRecycleViewDuringLongPress() throws Throwable {
+        final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0);
+        rvs.mLayoutManager.expectLayouts(1);
+        setRecyclerView(rvs.mWrappedRecyclerView);
+        rvs.mLayoutManager.waitForLayout(1);
+
+        final RecyclerView.ViewHolder target = mRecyclerView
+                .findViewHolderForAdapterPosition(1);
+        target.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                mItemTouchHelper.attachToRecyclerView(null);
+                return false;
+            }
+        });
+        TouchUtils.longClickView(getInstrumentation(), target.itemView);
+    }
+
+    @Test
+    public void attachToAnotherRecycleViewDuringLongPress() throws Throwable {
+        final RecyclerViewState rvs2 = setupRecyclerView();
+        rvs2.mLayoutManager.expectLayouts(1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().getContainer().addView(rvs2.mWrappedRecyclerView);
+            }
+        });
+        rvs2.mLayoutManager.waitForLayout(1);
+
+        final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0);
+        rvs.mLayoutManager.expectLayouts(1);
+        setRecyclerView(rvs.mWrappedRecyclerView);
+        rvs.mLayoutManager.waitForLayout(1);
+
+        final RecyclerView.ViewHolder target = mRecyclerView
+                .findViewHolderForAdapterPosition(1);
+        target.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                mItemTouchHelper.attachToRecyclerView(rvs2.mWrappedRecyclerView);
+                return false;
+            }
+        });
+        TouchUtils.longClickView(getInstrumentation(), target.itemView);
+        assertEquals(0, mCalback.mHasDragFlag.size());
+    }
+
     public void basicSwipeTest(int dir, int swipeDirs, int targetX) throws Throwable {
-        final RecyclerView recyclerView = setup(0, swipeDirs);
-        mLayoutManager.expectLayouts(1);
-        setRecyclerView(recyclerView);
-        mLayoutManager.waitForLayout(1);
+        final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), 0, swipeDirs);
+        rvs.mLayoutManager.expectLayouts(1);
+        setRecyclerView(rvs.mWrappedRecyclerView);
+        rvs.mLayoutManager.waitForLayout(1);
 
         final RecyclerView.ViewHolder target = mRecyclerView
                 .findViewHolderForAdapterPosition(1);
@@ -158,9 +215,9 @@
         assertEquals(1, mItemTouchHelper.mRecoverAnimations.size());
         assertEquals(1, mItemTouchHelper.mPendingCleanup.size());
         // get rid of the view
-        mLayoutManager.expectLayouts(1);
-        mAdapter.deleteAndNotify(1, 1);
-        mLayoutManager.waitForLayout(1);
+        rvs.mLayoutManager.expectLayouts(1);
+        rvs.mAdapter.deleteAndNotify(1, 1);
+        rvs.mLayoutManager.waitForLayout(1);
         waitForAnimations();
         assertEquals(0, mItemTouchHelper.mRecoverAnimations.size());
         assertEquals(0, mItemTouchHelper.mPendingCleanup.size());
@@ -181,6 +238,8 @@
 
         private List<RecyclerView.ViewHolder> mCleared = new ArrayList<RecyclerView.ViewHolder>();
 
+        public List<Pair<RecyclerView, RecyclerView.ViewHolder>> mHasDragFlag = new ArrayList<>();
+
         LoggingCalback(int dragDirs, int swipeDirs) {
             super(dragDirs, swipeDirs);
         }
@@ -212,6 +271,12 @@
             mCleared.add(viewHolder);
         }
 
+        @Override
+        boolean hasDragFlag(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
+            mHasDragFlag.add(new Pair<>(recyclerView, viewHolder));
+            return super.hasDragFlag(recyclerView, viewHolder);
+        }
+
         public SwipeRecord getSwipe(RecyclerView.ViewHolder vh) {
             for (SwipeRecord swipe : mSwipeRecords) {
                 if (swipe.viewHolder == vh) {