Merge "Throw if Activity is not attached to Application, when querying for VM" into oc-mr1-support-27.0-dev
diff --git a/compat/api/current.txt b/compat/api/current.txt
index c4e7fd3..85ad7f2 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -641,12 +641,12 @@
     field public static final java.lang.String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
   }
 
-  public final class SharedPreferencesCompat {
+  public final deprecated class SharedPreferencesCompat {
   }
 
-  public static final class SharedPreferencesCompat.EditorCompat {
-    method public void apply(android.content.SharedPreferences.Editor);
-    method public static android.support.v4.content.SharedPreferencesCompat.EditorCompat getInstance();
+  public static final deprecated class SharedPreferencesCompat.EditorCompat {
+    method public deprecated void apply(android.content.SharedPreferences.Editor);
+    method public static deprecated android.support.v4.content.SharedPreferencesCompat.EditorCompat getInstance();
   }
 
 }
diff --git a/compat/java/android/support/v4/content/SharedPreferencesCompat.java b/compat/java/android/support/v4/content/SharedPreferencesCompat.java
index 7d51fed..1d43c2e 100644
--- a/compat/java/android/support/v4/content/SharedPreferencesCompat.java
+++ b/compat/java/android/support/v4/content/SharedPreferencesCompat.java
@@ -19,8 +19,18 @@
 import android.content.SharedPreferences;
 import android.support.annotation.NonNull;
 
+/**
+ * @deprecated This compatibility class is no longer required. Use {@link SharedPreferences}
+ * directly.
+ */
+@Deprecated
 public final class SharedPreferencesCompat {
 
+    /**
+     * @deprecated This compatibility class is no longer required. Use
+     * {@link SharedPreferences.Editor} directly.
+     */
+    @Deprecated
     public final static class EditorCompat {
 
         private static EditorCompat sInstance;
@@ -46,14 +56,22 @@
         private EditorCompat() {
             mHelper = new Helper();
         }
-
+        /**
+         * @deprecated This compatibility class is no longer required. Use
+         * {@link SharedPreferences.Editor} directly.
+         */
+        @Deprecated
         public static EditorCompat getInstance() {
             if (sInstance == null) {
                 sInstance = new EditorCompat();
             }
             return sInstance;
         }
-
+        /**
+         * @deprecated This compatibility method is no longer required. Use
+         * {@link SharedPreferences.Editor#apply()} directly.
+         */
+        @Deprecated
         public void apply(@NonNull SharedPreferences.Editor editor) {
             // Note that this redirection is needed to not break the public API chain
             // of getInstance().apply() calls. Otherwise this method could (and should)
diff --git a/core-utils/Android.mk b/core-utils/Android.mk
index 5ea200e..6dda862 100644
--- a/core-utils/Android.mk
+++ b/core-utils/Android.mk
@@ -27,7 +27,6 @@
 LOCAL_MODULE := android-support-core-utils
 LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
 LOCAL_SRC_FILES := \
-    $(call all-java-files-under,gingerbread) \
     $(call all-java-files-under,kitkat) \
     $(call all-java-files-under,api21) \
     $(call all-java-files-under,java)
diff --git a/core-utils/build.gradle b/core-utils/build.gradle
index 0fe309b..29fe86c 100644
--- a/core-utils/build.gradle
+++ b/core-utils/build.gradle
@@ -17,12 +17,8 @@
 
     sourceSets {
         main.java.srcDirs = [
-                'gingerbread',
                 'kitkat',
-                'api20',
                 'api21',
-                'api23',
-                'api24',
                 'java'
         ]
     }
diff --git a/core-utils/java/android/support/v4/app/AppLaunchChecker.java b/core-utils/java/android/support/v4/app/AppLaunchChecker.java
index 0b2cc4f..af9512a 100644
--- a/core-utils/java/android/support/v4/app/AppLaunchChecker.java
+++ b/core-utils/java/android/support/v4/app/AppLaunchChecker.java
@@ -24,7 +24,6 @@
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.v4.content.IntentCompat;
-import android.support.v4.content.SharedPreferencesCompat;
 
 /**
  * This class provides APIs for determining how an app has been launched.
@@ -77,8 +76,7 @@
         if (Intent.ACTION_MAIN.equals(launchIntent.getAction())
                 && (launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
                 || launchIntent.hasCategory(IntentCompat.CATEGORY_LEANBACK_LAUNCHER))) {
-            SharedPreferencesCompat.EditorCompat.getInstance().apply(
-                    sp.edit().putBoolean(KEY_STARTED_FROM_LAUNCHER, true));
+            sp.edit().putBoolean(KEY_STARTED_FROM_LAUNCHER, true).apply();
         }
     }
 }
diff --git a/core-utils/java/android/support/v4/content/AsyncTaskLoader.java b/core-utils/java/android/support/v4/content/AsyncTaskLoader.java
index faa13ad..5882f69 100644
--- a/core-utils/java/android/support/v4/content/AsyncTaskLoader.java
+++ b/core-utils/java/android/support/v4/content/AsyncTaskLoader.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.os.OperationCanceledException;
 import android.support.v4.util.TimeUtils;
@@ -121,11 +123,11 @@
     long mLastLoadCompleteTime = -10000;
     Handler mHandler;
 
-    public AsyncTaskLoader(Context context) {
+    public AsyncTaskLoader(@NonNull Context context) {
         this(context, ModernAsyncTask.THREAD_POOL_EXECUTOR);
     }
 
-    private AsyncTaskLoader(Context context, Executor executor) {
+    private AsyncTaskLoader(@NonNull Context context, @NonNull Executor executor) {
         super(context);
         mExecutor = executor;
     }
@@ -200,7 +202,7 @@
      * @param data The value that was returned by {@link #loadInBackground}, or null
      * if the task threw {@link OperationCanceledException}.
      */
-    public void onCanceled(D data) {
+    public void onCanceled(@Nullable D data) {
     }
 
     void executePendingTask() {
@@ -284,6 +286,7 @@
      * @see #cancelLoadInBackground
      * @see #onCanceled
      */
+    @Nullable
     public abstract D loadInBackground();
 
     /**
@@ -298,6 +301,7 @@
      *
      * @see #loadInBackground
      */
+    @Nullable
     protected D onLoadInBackground() {
         return loadInBackground();
     }
diff --git a/core-utils/java/android/support/v4/content/CursorLoader.java b/core-utils/java/android/support/v4/content/CursorLoader.java
index 503bb9c..5c6925d 100644
--- a/core-utils/java/android/support/v4/content/CursorLoader.java
+++ b/core-utils/java/android/support/v4/content/CursorLoader.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v4.os.CancellationSignal;
 import android.support.v4.os.OperationCanceledException;
 
@@ -115,7 +117,7 @@
      * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
      * to specify the query to perform.
      */
-    public CursorLoader(Context context) {
+    public CursorLoader(@NonNull Context context) {
         super(context);
         mObserver = new ForceLoadContentObserver();
     }
@@ -126,8 +128,9 @@
      * ContentResolver.query()} for documentation on the meaning of the
      * parameters.  These will be passed as-is to that call.
      */
-    public CursorLoader(Context context, Uri uri, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) {
+    public CursorLoader(@NonNull Context context, @NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) {
         super(context);
         mObserver = new ForceLoadContentObserver();
         mUri = uri;
@@ -183,43 +186,48 @@
         mCursor = null;
     }
 
+    @NonNull
     public Uri getUri() {
         return mUri;
     }
 
-    public void setUri(Uri uri) {
+    public void setUri(@NonNull Uri uri) {
         mUri = uri;
     }
 
+    @Nullable
     public String[] getProjection() {
         return mProjection;
     }
 
-    public void setProjection(String[] projection) {
+    public void setProjection(@Nullable String[] projection) {
         mProjection = projection;
     }
 
+    @Nullable
     public String getSelection() {
         return mSelection;
     }
 
-    public void setSelection(String selection) {
+    public void setSelection(@Nullable String selection) {
         mSelection = selection;
     }
 
+    @Nullable
     public String[] getSelectionArgs() {
         return mSelectionArgs;
     }
 
-    public void setSelectionArgs(String[] selectionArgs) {
+    public void setSelectionArgs(@Nullable String[] selectionArgs) {
         mSelectionArgs = selectionArgs;
     }
 
+    @Nullable
     public String getSortOrder() {
         return mSortOrder;
     }
 
-    public void setSortOrder(String sortOrder) {
+    public void setSortOrder(@Nullable String sortOrder) {
         mSortOrder = sortOrder;
     }
 
diff --git a/core-utils/java/android/support/v4/content/FileProvider.java b/core-utils/java/android/support/v4/content/FileProvider.java
index c49fc12..8599911 100644
--- a/core-utils/java/android/support/v4/content/FileProvider.java
+++ b/core-utils/java/android/support/v4/content/FileProvider.java
@@ -33,6 +33,8 @@
 import android.os.ParcelFileDescriptor;
 import android.provider.OpenableColumns;
 import android.support.annotation.GuardedBy;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.webkit.MimeTypeMap;
 
@@ -362,7 +364,7 @@
      * @param info A {@link ProviderInfo} for the new provider.
      */
     @Override
-    public void attachInfo(Context context, ProviderInfo info) {
+    public void attachInfo(@NonNull Context context, @NonNull ProviderInfo info) {
         super.attachInfo(context, info);
 
         // Sanity check our security
@@ -396,7 +398,8 @@
      * @throws IllegalArgumentException When the given {@link File} is outside
      * the paths supported by the provider.
      */
-    public static Uri getUriForFile(Context context, String authority, File file) {
+    public static Uri getUriForFile(@NonNull Context context, @NonNull String authority,
+            @NonNull File file) {
         final PathStrategy strategy = getPathStrategy(context, authority);
         return strategy.getUriForFile(file);
     }
@@ -430,8 +433,9 @@
      *
      */
     @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) {
         // ContentProvider has already checked granted permissions
         final File file = mStrategy.getFileForUri(uri);
 
@@ -470,7 +474,7 @@
      * extension; otherwise <code>application/octet-stream</code>.
      */
     @Override
-    public String getType(Uri uri) {
+    public String getType(@NonNull Uri uri) {
         // ContentProvider has already checked granted permissions
         final File file = mStrategy.getFileForUri(uri);
 
@@ -491,7 +495,7 @@
      * subclass FileProvider if you want to provide different functionality.
      */
     @Override
-    public Uri insert(Uri uri, ContentValues values) {
+    public Uri insert(@NonNull Uri uri, ContentValues values) {
         throw new UnsupportedOperationException("No external inserts");
     }
 
@@ -500,7 +504,8 @@
      * subclass FileProvider if you want to provide different functionality.
      */
     @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+    public int update(@NonNull Uri uri, ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
         throw new UnsupportedOperationException("No external updates");
     }
 
@@ -516,7 +521,8 @@
      * @return 1 if the delete succeeds; otherwise, 0.
      */
     @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
         // ContentProvider has already checked granted permissions
         final File file = mStrategy.getFileForUri(uri);
         return file.delete() ? 1 : 0;
@@ -538,7 +544,8 @@
      * @return A new {@link ParcelFileDescriptor} with which you can access the file.
      */
     @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+    public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
+            throws FileNotFoundException {
         // ContentProvider has already checked granted permissions
         final File file = mStrategy.getFileForUri(uri);
         final int fileMode = modeToMode(mode);
diff --git a/core-utils/java/android/support/v4/content/Loader.java b/core-utils/java/android/support/v4/content/Loader.java
index 40b459f..2ac10d7 100644
--- a/core-utils/java/android/support/v4/content/Loader.java
+++ b/core-utils/java/android/support/v4/content/Loader.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v4.util.DebugUtils;
 
 import java.io.FileDescriptor;
@@ -80,7 +82,7 @@
          * @param loader the loader that completed the load
          * @param data the result of the load
          */
-        public void onLoadComplete(Loader<D> loader, D data);
+        void onLoadComplete(@NonNull Loader<D> loader, @Nullable D data);
     }
 
     /**
@@ -97,7 +99,7 @@
          *
          * @param loader the loader that canceled the load
          */
-        public void onLoadCanceled(Loader<D> loader);
+        void onLoadCanceled(@NonNull Loader<D> loader);
     }
 
     /**
@@ -110,7 +112,7 @@
      *
      * @param context used to retrieve the application context.
      */
-    public Loader(Context context) {
+    public Loader(@NonNull Context context) {
         mContext = context.getApplicationContext();
     }
 
@@ -121,7 +123,7 @@
      *
      * @param data the result of the load
      */
-    public void deliverResult(D data) {
+    public void deliverResult(@Nullable D data) {
         if (mListener != null) {
             mListener.onLoadComplete(this, data);
         }
@@ -142,6 +144,7 @@
     /**
      * @return an application context retrieved from the Context passed to the constructor.
      */
+    @NonNull
     public Context getContext() {
         return mContext;
     }
@@ -160,7 +163,7 @@
      *
      * <p>Must be called from the process's main thread.
      */
-    public void registerListener(int id, OnLoadCompleteListener<D> listener) {
+    public void registerListener(int id, @NonNull OnLoadCompleteListener<D> listener) {
         if (mListener != null) {
             throw new IllegalStateException("There is already a listener registered");
         }
@@ -173,7 +176,7 @@
      *
      * Must be called from the process's main thread.
      */
-    public void unregisterListener(OnLoadCompleteListener<D> listener) {
+    public void unregisterListener(@NonNull OnLoadCompleteListener<D> listener) {
         if (mListener == null) {
             throw new IllegalStateException("No listener register");
         }
@@ -192,7 +195,7 @@
      *
      * @param listener The listener to register.
      */
-    public void registerOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {
+    public void registerOnLoadCanceledListener(@NonNull OnLoadCanceledListener<D> listener) {
         if (mOnLoadCanceledListener != null) {
             throw new IllegalStateException("There is already a listener registered");
         }
@@ -207,7 +210,7 @@
      *
      * @param listener The listener to unregister.
      */
-    public void unregisterOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {
+    public void unregisterOnLoadCanceledListener(@NonNull OnLoadCanceledListener<D> listener) {
         if (mOnLoadCanceledListener == null) {
             throw new IllegalStateException("No listener register");
         }
@@ -493,7 +496,8 @@
      * For debugging, converts an instance of the Loader's data class to
      * a string that can be printed.  Must handle a null data.
      */
-    public String dataToString(D data) {
+    @NonNull
+    public String dataToString(@Nullable D data) {
         StringBuilder sb = new StringBuilder(64);
         DebugUtils.buildShortClassTag(data, sb);
         sb.append("}");
diff --git a/core-utils/java/android/support/v4/content/LocalBroadcastManager.java b/core-utils/java/android/support/v4/content/LocalBroadcastManager.java
index 324bb30..aaaf8be 100644
--- a/core-utils/java/android/support/v4/content/LocalBroadcastManager.java
+++ b/core-utils/java/android/support/v4/content/LocalBroadcastManager.java
@@ -16,10 +16,6 @@
 
 package android.support.v4.content;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Set;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,8 +23,13 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
+import android.support.annotation.NonNull;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+
 /**
  * Helper to register for and send broadcasts of Intents to local objects
  * within your process.  This has a number of advantages over sending
@@ -98,7 +99,8 @@
     private static final Object mLock = new Object();
     private static LocalBroadcastManager mInstance;
 
-    public static LocalBroadcastManager getInstance(Context context) {
+    @NonNull
+    public static LocalBroadcastManager getInstance(@NonNull Context context) {
         synchronized (mLock) {
             if (mInstance == null) {
                 mInstance = new LocalBroadcastManager(context.getApplicationContext());
@@ -132,7 +134,8 @@
      *
      * @see #unregisterReceiver
      */
-    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+    public void registerReceiver(@NonNull BroadcastReceiver receiver,
+            @NonNull IntentFilter filter) {
         synchronized (mReceivers) {
             ReceiverRecord entry = new ReceiverRecord(filter, receiver);
             ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
@@ -162,7 +165,7 @@
      *
      * @see #registerReceiver
      */
-    public void unregisterReceiver(BroadcastReceiver receiver) {
+    public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {
         synchronized (mReceivers) {
             final ArrayList<ReceiverRecord> filters = mReceivers.remove(receiver);
             if (filters == null) {
@@ -205,7 +208,7 @@
      * broadcast receivers.  (Note tha delivery may not ultimately take place if one of those
      * receivers is unregistered before it is dispatched.)
      */
-    public boolean sendBroadcast(Intent intent) {
+    public boolean sendBroadcast(@NonNull Intent intent) {
         synchronized (mReceivers) {
             final String action = intent.getAction();
             final String type = intent.resolveTypeIfNeeded(
@@ -281,7 +284,7 @@
      * the Intent this function will block and immediately dispatch them before
      * returning.
      */
-    public void sendBroadcastSync(Intent intent) {
+    public void sendBroadcastSync(@NonNull Intent intent) {
         if (sendBroadcast(intent)) {
             executePendingBroadcasts();
         }
diff --git a/core-utils/java/android/support/v4/content/MimeTypeFilter.java b/core-utils/java/android/support/v4/content/MimeTypeFilter.java
index 8734c4d..8a90c62 100644
--- a/core-utils/java/android/support/v4/content/MimeTypeFilter.java
+++ b/core-utils/java/android/support/v4/content/MimeTypeFilter.java
@@ -87,6 +87,7 @@
      * Matches one nullable MIME type against an array of MIME type filters.
      * @return The first matching filter, or null if nothing matches.
      */
+    @Nullable
     public static String matches(
             @Nullable String mimeType, @NonNull String[] filters) {
         if (mimeType == null) {
@@ -108,6 +109,7 @@
      * Matches multiple MIME types against an array of MIME type filters.
      * @return The first matching MIME type, or null if nothing matches.
      */
+    @Nullable
     public static String matches(
             @Nullable String[] mimeTypes, @NonNull String filter) {
         if (mimeTypes == null) {
@@ -129,6 +131,7 @@
      * Matches multiple MIME types against an array of MIME type filters.
      * @return The list of matching MIME types, or empty array if nothing matches.
      */
+    @NonNull
     public static String[] matchesMany(
             @Nullable String[] mimeTypes, @NonNull String filter) {
         if (mimeTypes == null) {
diff --git a/core-utils/java/android/support/v4/content/PermissionChecker.java b/core-utils/java/android/support/v4/content/PermissionChecker.java
index 0866273..c9f18a9 100644
--- a/core-utils/java/android/support/v4/content/PermissionChecker.java
+++ b/core-utils/java/android/support/v4/content/PermissionChecker.java
@@ -24,6 +24,7 @@
 import android.os.Process;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.app.AppOpsManagerCompat;
 
@@ -91,7 +92,7 @@
      */
     @PermissionResult
     public static int checkPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, String packageName) {
+            int pid, int uid, @Nullable String packageName) {
         if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
             return PERMISSION_DENIED;
         }
@@ -146,7 +147,7 @@
      */
     @PermissionResult
     public static int checkCallingPermission(@NonNull Context context,
-            @NonNull String permission, String packageName) {
+            @NonNull String permission, @Nullable String packageName) {
         if (Binder.getCallingPid() == Process.myPid()) {
             return PERMISSION_DENIED;
         }
diff --git a/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java b/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
similarity index 97%
rename from core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
rename to core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
index d515561..795126d 100644
--- a/core-utils/gingerbread/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
+++ b/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
@@ -27,6 +27,8 @@
 import android.graphics.RectF;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.util.DisplayMetrics;
 import android.view.Gravity;
@@ -66,6 +68,7 @@
     /**
      * Returns the paint used to render this drawable.
      */
+    @NonNull
     public final Paint getPaint() {
         return mPaint;
     }
@@ -73,6 +76,7 @@
     /**
      * Returns the bitmap used by this drawable to render. May be null.
      */
+    @Nullable
     public final Bitmap getBitmap() {
         return mBitmap;
     }
@@ -92,7 +96,7 @@
      * @see android.graphics.Bitmap#setDensity(int)
      * @see android.graphics.Bitmap#getDensity()
      */
-    public void setTargetDensity(Canvas canvas) {
+    public void setTargetDensity(@NonNull Canvas canvas) {
         setTargetDensity(canvas.getDensity());
     }
 
@@ -104,7 +108,7 @@
      * @see android.graphics.Bitmap#setDensity(int)
      * @see android.graphics.Bitmap#getDensity()
      */
-    public void setTargetDensity(DisplayMetrics metrics) {
+    public void setTargetDensity(@NonNull DisplayMetrics metrics) {
         setTargetDensity(metrics.densityDpi);
     }
 
@@ -253,7 +257,7 @@
     }
 
     @Override
-    public void draw(Canvas canvas) {
+    public void draw(@NonNull Canvas canvas) {
         final Bitmap bitmap = mBitmap;
         if (bitmap == null) {
             return;
diff --git a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java b/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
index 5e144c7..7790055 100644
--- a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
+++ b/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
@@ -21,11 +21,15 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
 import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v4.graphics.BitmapCompat;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
 import android.util.Log;
 
+import java.io.InputStream;
+
 /**
  * Constructs {@link RoundedBitmapDrawable RoundedBitmapDrawable} objects,
  * either from Bitmaps directly, or from streams and files.
@@ -63,7 +67,8 @@
      * Returns a new drawable by creating it from a bitmap, setting initial target density based on
      * the display metrics of the resources.
      */
-    public static RoundedBitmapDrawable create(Resources res, Bitmap bitmap) {
+    @NonNull
+    public static RoundedBitmapDrawable create(@NonNull Resources res, @Nullable Bitmap bitmap) {
         if (Build.VERSION.SDK_INT >= 21) {
             return new RoundedBitmapDrawable21(res, bitmap);
         }
@@ -73,8 +78,8 @@
     /**
      * Returns a new drawable, creating it by opening a given file path and decoding the bitmap.
      */
-    public static RoundedBitmapDrawable create(Resources res,
-            String filepath) {
+    @NonNull
+    public static RoundedBitmapDrawable create(@NonNull Resources res, @NonNull String filepath) {
         final RoundedBitmapDrawable drawable = create(res, BitmapFactory.decodeFile(filepath));
         if (drawable.getBitmap() == null) {
             Log.w(TAG, "RoundedBitmapDrawable cannot decode " + filepath);
@@ -86,8 +91,8 @@
     /**
      * Returns a new drawable, creating it by decoding a bitmap from the given input stream.
      */
-    public static RoundedBitmapDrawable create(Resources res,
-            java.io.InputStream is) {
+    @NonNull
+    public static RoundedBitmapDrawable create(@NonNull Resources res, @NonNull InputStream is) {
         final RoundedBitmapDrawable drawable = create(res, BitmapFactory.decodeStream(is));
         if (drawable.getBitmap() == null) {
             Log.w(TAG, "RoundedBitmapDrawable cannot decode " + is);
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 c9e3e18..0d957dc 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
@@ -112,7 +112,7 @@
         val indexInputs = entityIndices + fieldIndices + superIndices
         val indices = validateAndCreateIndices(indexInputs, pojo)
 
-        val primaryKey = findPrimaryKey(pojo.fields, pojo.embeddedFields)
+        val primaryKey = findAndValidatePrimaryKey(pojo.fields, pojo.embeddedFields)
         val affinity = primaryKey.fields.firstOrNull()?.affinity ?: SQLTypeAffinity.TEXT
         context.checker.check(
                 !primaryKey.autoGenerateId || affinity == SQLTypeAffinity.INTEGER,
@@ -226,7 +226,7 @@
         }.filterNotNull()
     }
 
-    private fun findPrimaryKey(fields: List<Field>, embeddedFields: List<EmbeddedField>)
+    private fun findAndValidatePrimaryKey(fields: List<Field>, embeddedFields: List<EmbeddedField>)
             : PrimaryKey {
         val candidates = collectPrimaryKeysFromEntityAnnotations(element, fields) +
                 collectPrimaryKeysFromPrimaryKeyAnnotations(fields) +
@@ -242,7 +242,15 @@
                 .map { candidate ->
                     candidate.fields.map { field ->
                         context.checker.check(field.nonNull, field.element,
-                                ProcessorErrors.PRIMARY_KEY_NULL)
+                                ProcessorErrors.primaryKeyNull(field.getPath()))
+                        // Validate parents for nullability
+                        var parent = field.parent
+                        while(parent != null) {
+                            val parentField = parent.field
+                            context.checker.check(parentField.nonNull, parentField.element,
+                                    ProcessorErrors.primaryKeyNull(parentField.getPath()))
+                            parent = parentField.parent
+                        }
                     }
                 }
 
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 a576aa2..62429eb 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
@@ -25,7 +25,6 @@
 import android.arch.persistence.room.vo.CustomTypeConverter
 import android.arch.persistence.room.vo.Field
 import com.squareup.javapoet.TypeName
-import javax.lang.model.type.TypeMirror
 
 object ProcessorErrors {
     private fun String.trim(): String {
@@ -134,9 +133,9 @@
     val LIVE_DATA_QUERY_WITHOUT_SELECT = "LiveData return type can only be used with SELECT" +
             " queries."
 
-    val LIVE_DATA_QUERY_NOTHING_TO_OBSERVE = "LiveData return type can only be used with SELECT" +
-            " queries that directly or indirectly (via @Relation, for example) access at least" +
-            " one table.";
+    val OBSERVABLE_QUERY_NOTHING_TO_OBSERVE = "Observable query return type (LiveData, Flowable" +
+            " etc) can only be used with SELECT queries that directly or indirectly (via" +
+            " @Relation, for example) access at least one table."
 
     private val TOO_MANY_MATCHING_GETTERS = "Ambiguous getter for %s. All of the following " +
             "match: %s. You can @Ignore the ones that you don't want to match."
@@ -450,7 +449,10 @@
 
     val PAGING_SPECIFY_DATA_SOURCE_TYPE = "For now, Room only supports TiledDataSource class."
 
-    val PRIMARY_KEY_NULL = "You must annotate primary keys with @NonNull. SQLite considers this a " +
-            "bug and Room does not allow it. See SQLite docs for details: " +
-            "https://www.sqlite.org/lang_createtable.html"
+    fun primaryKeyNull(field: String): String{
+        return "You must annotate primary keys with @NonNull. \"$field\" is nullable. SQLite " +
+                "considers this a " +
+                "bug and Room does not allow it. See SQLite docs for details: " +
+                "https://www.sqlite.org/lang_createtable.html"
+    }
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt
new file mode 100644
index 0000000..89b0072
--- /dev/null
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/ObservableQueryResultBinderProvider.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.persistence.room.solver
+
+import android.arch.persistence.room.parser.ParsedQuery
+import android.arch.persistence.room.processor.Context
+import android.arch.persistence.room.processor.ProcessorErrors
+import android.arch.persistence.room.solver.query.result.QueryResultAdapter
+import android.arch.persistence.room.solver.query.result.QueryResultBinder
+import javax.lang.model.type.DeclaredType
+import javax.lang.model.type.TypeMirror
+
+/**
+ * Binder provider class that has common functionality for observables.
+ */
+abstract class ObservableQueryResultBinderProvider(val context: Context)
+    : QueryResultBinderProvider {
+    protected abstract fun extractTypeArg(declared: DeclaredType) : TypeMirror
+    protected abstract fun create(typeArg: TypeMirror,
+                                  resultAdapter: QueryResultAdapter?,
+                                  tableNames : Set<String>) : QueryResultBinder
+
+    override final fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
+        val typeArg = extractTypeArg(declared)
+        val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
+        val tableNames = ((adapter?.accessedTableNames() ?: emptyList()) +
+                query.tables.map { it.name }).toSet()
+        context.checker.check(!tableNames.isEmpty(),
+                declared.asElement(),
+                ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+        return create(
+                typeArg = typeArg,
+                resultAdapter = adapter,
+                tableNames = tableNames
+        )
+    }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/FlowableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/FlowableQueryResultBinderProvider.kt
index 828f5a7..6a2c901 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/FlowableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/FlowableQueryResultBinderProvider.kt
@@ -18,17 +18,17 @@
 
 import android.arch.persistence.room.ext.RoomRxJava2TypeNames
 import android.arch.persistence.room.ext.RxJava2TypeNames
-import android.arch.persistence.room.parser.ParsedQuery
 import android.arch.persistence.room.processor.Context
 import android.arch.persistence.room.processor.ProcessorErrors
-import android.arch.persistence.room.solver.QueryResultBinderProvider
+import android.arch.persistence.room.solver.ObservableQueryResultBinderProvider
 import android.arch.persistence.room.solver.query.result.FlowableQueryResultBinder
+import android.arch.persistence.room.solver.query.result.QueryResultAdapter
 import android.arch.persistence.room.solver.query.result.QueryResultBinder
-import com.google.common.annotations.VisibleForTesting
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
-class FlowableQueryResultBinderProvider(val context : Context) : QueryResultBinderProvider {
+class FlowableQueryResultBinderProvider(context: Context) :
+        ObservableQueryResultBinderProvider(context) {
     private val flowableTypeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
                 .getTypeElement(RxJava2TypeNames.FLOWABLE.toString())?.asType()
@@ -39,10 +39,14 @@
                 .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
     }
 
-    override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
-        val typeArg = declared.typeArguments.first()
-        return FlowableQueryResultBinder(typeArg, query.tables.map { it.name },
-                context.typeAdapterStore.findQueryResultAdapter(typeArg, query))
+    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
+
+    override fun create(typeArg: TypeMirror, resultAdapter: QueryResultAdapter?,
+                        tableNames: Set<String>): QueryResultBinder {
+        return FlowableQueryResultBinder(
+                typeArg = typeArg,
+                queryTableNames = tableNames,
+                adapter = resultAdapter)
     }
 
     override fun matches(declared: DeclaredType): Boolean =
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
index 7e6725f..650ec19 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
@@ -17,34 +17,29 @@
 package android.arch.persistence.room.solver.binderprovider
 
 import android.arch.persistence.room.ext.LifecyclesTypeNames
-import android.arch.persistence.room.parser.ParsedQuery
 import android.arch.persistence.room.processor.Context
-import android.arch.persistence.room.processor.ProcessorErrors
-import android.arch.persistence.room.solver.QueryResultBinderProvider
+import android.arch.persistence.room.solver.ObservableQueryResultBinderProvider
 import android.arch.persistence.room.solver.query.result.LiveDataQueryResultBinder
+import android.arch.persistence.room.solver.query.result.QueryResultAdapter
 import android.arch.persistence.room.solver.query.result.QueryResultBinder
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
-class LiveDataQueryResultBinderProvider(val context : Context) : QueryResultBinderProvider {
+class LiveDataQueryResultBinderProvider(context : Context)
+    : ObservableQueryResultBinderProvider(context) {
     private val liveDataTypeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
                 .getTypeElement(LifecyclesTypeNames.LIVE_DATA.toString())?.asType()
     }
 
-    override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
-        val liveDataTypeArg = declared.typeArguments.first()
-        val queryResultAdapter =
-                context.typeAdapterStore.findQueryResultAdapter(liveDataTypeArg, query)
-        val tableNames = ((queryResultAdapter?.accessedTableNames() ?: emptyList()) +
-                        query.tables.map { it.name }).toSet()
-        context.checker.check(!tableNames.isEmpty(),
-                              declared.asElement(),
-                              ProcessorErrors.LIVE_DATA_QUERY_NOTHING_TO_OBSERVE);
+    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
+
+    override fun create(typeArg: TypeMirror, resultAdapter: QueryResultAdapter?,
+                        tableNames: Set<String>): QueryResultBinder {
         return LiveDataQueryResultBinder(
-                liveDataTypeArg,
-                tableNames,
-                queryResultAdapter)
+                typeArg = typeArg,
+                tableNames = tableNames,
+                adapter = resultAdapter)
     }
 
     override fun matches(declared: DeclaredType): Boolean =
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
index dbd66ce..5c8e3e7 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder.kt
@@ -34,7 +34,7 @@
 /**
  * Binds the result as an RxJava2 Flowable.
  */
-class FlowableQueryResultBinder(val typeArg: TypeMirror, val queryTableNames: List<String>,
+class FlowableQueryResultBinder(val typeArg: TypeMirror, val queryTableNames: Set<String>,
                                 adapter: QueryResultAdapter?)
     : BaseObservableQueryResultBinder(adapter) {
     override fun convertAndReturn(roomSQLiteQueryVar: String, dbField: FieldSpec,
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 c25d001..ababef6 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
@@ -18,7 +18,6 @@
 
 import COMMON
 import android.arch.persistence.room.parser.SQLTypeAffinity
-import android.arch.persistence.room.processor.ProcessorErrors.PRIMARY_KEY_NULL
 import android.arch.persistence.room.processor.ProcessorErrors.RELATION_IN_ENTITY
 import android.arch.persistence.room.vo.CallType
 import android.arch.persistence.room.vo.Field
@@ -1163,7 +1162,7 @@
             """) { entity, _ ->
             assertThat(entity.primaryKey.fields.size, `is`(1))
             assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
-        }.failsToCompile().withErrorContaining(PRIMARY_KEY_NULL)
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("id"))
     }
 
     @Test
@@ -1175,7 +1174,8 @@
             @PrimaryKey
             public String anotherId;
             """) { entity, _ ->
-        }.failsToCompile().withErrorContaining(PRIMARY_KEY_NULL)
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("id"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("anotherId"))
     }
 
     @Test
@@ -1188,7 +1188,7 @@
             @PrimaryKey
             public String anotherId;
             """) { entity, _ ->
-        }.failsToCompile().withErrorContaining(PRIMARY_KEY_NULL)
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("anotherId"))
     }
 
     @Test
@@ -1199,7 +1199,7 @@
                 public String foo;
                 """,
                 attributes = mapOf("primaryKeys" to "{\"id\", \"foo\"}")) { _, _ ->
-        }.failsToCompile().withErrorContaining(PRIMARY_KEY_NULL)
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
     }
 
     @Test
@@ -1216,6 +1216,176 @@
     }
 
     @Test
+    fun primaryKey_nullableEmbedded(){
+        singleEntity(
+                """
+                public int id;
+
+                @Embedded(prefix = "bar_")
+                @PrimaryKey
+                public Foo foo;
+
+                static class Foo {
+                    public int a;
+                    public int b;
+                }
+                """) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+    }
+
+    @Test
+    fun primaryKey_nullableEmbeddedObject(){
+        singleEntity(
+                """
+                public int id;
+
+                @Embedded(prefix = "bar_")
+                @PrimaryKey
+                public Foo foo;
+
+                static class Foo {
+                    public String a;
+                    public String b;
+                }
+                """) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+                .and().withErrorCount(3)
+    }
+
+    @Test
+    fun primaryKey_nullableEmbeddedObject_multipleParents(){
+        singleEntity(
+                """
+                public int id;
+
+                @Embedded(prefix = "bar_")
+                @PrimaryKey
+                public Foo foo;
+
+                static class Foo {
+                @Embedded(prefix = "baz_")
+                public Baz a;
+                public String b;
+
+                static class Baz {
+                    public String bb;
+                }
+            }
+                """) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a > bb"))
+                .and().withErrorCount(4)
+    }
+
+    @Test
+    fun primaryKey_nullableEmbeddedInherited(){
+        val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
+                """
+                package foo.bar;
+                import android.support.annotation.NonNull;
+                import android.arch.persistence.room.*;
+
+                public class Base {
+                    long baseId;
+                    String name, lastName;
+                    @Embedded(prefix = "bar_")
+                    @PrimaryKey
+                    public Foo foo;
+
+                    static class Foo {
+                        public int a;
+                        public int b;
+                    }
+                }
+                """)
+        singleEntity(
+                """
+                public int id;
+                """,
+                baseClass = "foo.bar.Base",
+                jfos = listOf(parent)) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+                .and().withErrorCount(3)
+    }
+
+    @Test
+    fun primaryKey_nullableOverrideViaEmbedded() {
+        val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
+                """
+                package foo.bar;
+                import android.arch.persistence.room.*;
+
+                @Entity(primaryKeys = "baseId")
+                public class Base {
+                    long baseId;
+                    String name, lastName;
+                }
+                """)
+        singleEntity(
+                """
+                public int id;
+                @Embedded(prefix = "bar_")
+                @PrimaryKey
+                public Foo foo;
+
+                static class Foo {
+                    public int a;
+                    public int b;
+                }
+                """,
+                baseClass = "foo.bar.Base",
+                jfos = listOf(parent)) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+                .and().withNoteContaining(
+                "PrimaryKey[baseId] is overridden by PrimaryKey[foo > a, foo > b]")
+                .and().withErrorCount(3)
+    }
+
+    @Test
+    fun primaryKey_nullableOverrideEmbedded() {
+        val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
+                """
+                package foo.bar;
+                import android.support.annotation.NonNull;
+                import android.arch.persistence.room.*;
+
+                public class Base {
+                    long baseId;
+                    String name, lastName;
+                    @Embedded(prefix = "bar_")
+                    @PrimaryKey
+                    public Foo foo;
+
+                    static class Foo {
+                        public int a;
+                        public int b;
+                    }
+                }
+                """)
+        singleEntity(
+                """
+                @PrimaryKey
+                public int id;
+                """,
+                baseClass = "foo.bar.Base",
+                jfos = listOf(parent)) { _, _ ->
+        }.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+                .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+                .and().withNoteContaining(
+                "PrimaryKey[foo > a, foo > b] is overridden by PrimaryKey[id]")
+                .and().withErrorCount(3)
+    }
+
+    @Test
     fun relationInEntity() {
         singleEntity(
                 """
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 1172194..7e892b7 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
@@ -312,7 +312,7 @@
                 """) { _, _ ->
             // do nothing
         }.failsToCompile()
-                .withErrorContaining(ProcessorErrors.LIVE_DATA_QUERY_NOTHING_TO_OBSERVE)
+                .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
     }
 
     @Test
@@ -324,7 +324,7 @@
                 """) { _, _ ->
             // do nothing
         }.failsToCompile()
-                .withErrorContaining(ProcessorErrors.LIVE_DATA_QUERY_NOTHING_TO_OBSERVE)
+                .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
     }
 
     @Test
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java
index 3507aee..eb15901 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java
@@ -33,6 +33,8 @@
 
 import java.util.List;
 
+import io.reactivex.Flowable;
+
 @Dao
 public interface UserPetDao {
     @Query("SELECT * FROM User u, Pet p WHERE u.mId = p.mUserId")
@@ -62,6 +64,9 @@
     @Query("SELECT * FROM User u where u.mId = :userId")
     LiveData<UserAndAllPets> liveUserWithPets(int userId);
 
+    @Query("SELECT * FROM User u where u.mId = :userId")
+    Flowable<UserAndAllPets> flowableUserWithPets(int userId);
+
     @Query("SELECT * FROM User u where u.mId = :uid")
     EmbeddedUserAndAllPets loadUserAndPetsAsEmbedded(int uid);
 
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 1bbc140..98783f2 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
@@ -22,7 +22,9 @@
 import android.arch.core.executor.AppToolkitTaskExecutor;
 import android.arch.core.executor.TaskExecutor;
 import android.arch.persistence.room.EmptyResultSetException;
+import android.arch.persistence.room.integration.testapp.vo.Pet;
 import android.arch.persistence.room.integration.testapp.vo.User;
+import android.arch.persistence.room.integration.testapp.vo.UserAndAllPets;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -38,6 +40,7 @@
 import java.util.List;
 
 import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Predicate;
 import io.reactivex.observers.TestObserver;
 import io.reactivex.schedulers.TestScheduler;
 import io.reactivex.subscribers.TestSubscriber;
@@ -269,4 +272,37 @@
         subscriber.cancel();
         subscriber.assertNoErrors();
     }
+
+    @Test
+    public void flowableWithRelation() throws InterruptedException {
+        final TestSubscriber<UserAndAllPets> subscriber = new TestSubscriber<>();
+
+        mUserPetDao.flowableUserWithPets(3).subscribe(subscriber);
+        drain();
+        subscriber.assertSubscribed();
+
+        drain();
+        subscriber.assertNoValues();
+
+        final User user = TestUtil.createUser(3);
+        mUserDao.insert(user);
+        drain();
+        subscriber.assertValue(new Predicate<UserAndAllPets>() {
+            @Override
+            public boolean test(UserAndAllPets userAndAllPets) throws Exception {
+                return userAndAllPets.user.equals(user);
+            }
+        });
+        subscriber.assertValueCount(1);
+        final Pet[] pets = TestUtil.createPetsForUser(3, 1, 2);
+        mPetDao.insertAll(pets);
+        drain();
+        subscriber.assertValueAt(1, new Predicate<UserAndAllPets>() {
+            @Override
+            public boolean test(UserAndAllPets userAndAllPets) throws Exception {
+                return userAndAllPets.user.equals(user)
+                        && userAndAllPets.pets.equals(Arrays.asList(pets));
+            }
+        });
+    }
 }
diff --git a/v7/preference/src/android/support/v7/preference/Preference.java b/v7/preference/src/android/support/v7/preference/Preference.java
index cfc4311..fa8461d 100644
--- a/v7/preference/src/android/support/v7/preference/Preference.java
+++ b/v7/preference/src/android/support/v7/preference/Preference.java
@@ -31,7 +31,6 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.content.SharedPreferencesCompat;
 import android.support.v4.content.res.TypedArrayUtils;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
 import android.text.TextUtils;
@@ -1543,7 +1542,7 @@
 
     private void tryCommit(@NonNull SharedPreferences.Editor editor) {
         if (mPreferenceManager.shouldCommit()) {
-            SharedPreferencesCompat.EditorCompat.getInstance().apply(editor);
+            editor.apply();
         }
     }
 
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceManager.java b/v7/preference/src/android/support/v7/preference/PreferenceManager.java
index 83af86c..19b6908 100644
--- a/v7/preference/src/android/support/v7/preference/PreferenceManager.java
+++ b/v7/preference/src/android/support/v7/preference/PreferenceManager.java
@@ -25,7 +25,6 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.content.SharedPreferencesCompat;
 import android.text.TextUtils;
 
 /**
@@ -464,10 +463,9 @@
             pm.setSharedPreferencesMode(sharedPreferencesMode);
             pm.inflateFromResource(context, resId, null);
 
-            SharedPreferences.Editor editor =
-                    defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true);
-
-            SharedPreferencesCompat.EditorCompat.getInstance().apply(editor);
+            defaultValueSp.edit()
+                    .putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true)
+                    .apply();
         }
     }
 
@@ -511,7 +509,7 @@
 
     private void setNoCommit(boolean noCommit) {
         if (!noCommit && mEditor != null) {
-            SharedPreferencesCompat.EditorCompat.getInstance().apply(mEditor);
+            mEditor.apply();
         }
         mNoCommit = noCommit;
     }