Merge "Deprecate LoaderCallback, create MetadataLoaderRepoCallback" into oc-support-26.0-dev
diff --git a/api/26.0.0-SNAPSHOT.txt b/api/26.0.0-SNAPSHOT.txt
index 81069c3..9e9a646 100644
--- a/api/26.0.0-SNAPSHOT.txt
+++ b/api/26.0.0-SNAPSHOT.txt
@@ -2224,6 +2224,15 @@
     method public android.support.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
   }
 
+  public class TransitionListenerAdapter implements android.support.transition.Transition.TransitionListener {
+    ctor public TransitionListenerAdapter();
+    method public void onTransitionCancel(android.support.transition.Transition);
+    method public void onTransitionEnd(android.support.transition.Transition);
+    method public void onTransitionPause(android.support.transition.Transition);
+    method public void onTransitionResume(android.support.transition.Transition);
+    method public void onTransitionStart(android.support.transition.Transition);
+  }
+
   public class TransitionManager {
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
diff --git a/compat/build.gradle b/compat/build.gradle
index 0274285..fc61134 100644
--- a/compat/build.gradle
+++ b/compat/build.gradle
@@ -13,6 +13,7 @@
     androidTestCompile libs.mockito_core
     androidTestCompile libs.dexmaker
     androidTestCompile libs.dexmaker_mockito
+    androidTestCompile project(':support-testutils')
 }
 
 android {
diff --git a/compat/java/android/support/v4/app/JobIntentService.java b/compat/java/android/support/v4/app/JobIntentService.java
index a5417e6..0789039 100644
--- a/compat/java/android/support/v4/app/JobIntentService.java
+++ b/compat/java/android/support/v4/app/JobIntentService.java
@@ -32,7 +32,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
-import android.support.v4.os.BuildCompat;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -481,7 +480,7 @@
     static WorkEnqueuer getWorkEnqueuer(Context context, Class cls, boolean hasJobId, int jobId) {
         WorkEnqueuer we = sClassWorkEnqueuer.get(cls);
         if (we == null) {
-            if (BuildCompat.isAtLeastO()) {
+            if (Build.VERSION.SDK_INT >= 26) {
                 if (!hasJobId) {
                     throw new IllegalArgumentException("Can't be here without a job id");
                 }
diff --git a/compat/java/android/support/v4/app/NotificationCompat.java b/compat/java/android/support/v4/app/NotificationCompat.java
index ec46c55..d1cf9db 100644
--- a/compat/java/android/support/v4/app/NotificationCompat.java
+++ b/compat/java/android/support/v4/app/NotificationCompat.java
@@ -36,7 +36,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.GravityCompat;
 import android.view.Gravity;
 import android.widget.RemoteViews;
@@ -946,7 +945,7 @@
     }
 
     static {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             IMPL = new NotificationCompatApi26Impl();
         } else if (Build.VERSION.SDK_INT >= 24) {
             IMPL = new NotificationCompatApi24Impl();
@@ -4410,7 +4409,7 @@
      * @return the ID of the channel this notification posts to.
      */
     public static String getChannelId(Notification notification) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return notification.getChannelId();
         } else {
             return null;
@@ -4428,7 +4427,7 @@
      * canceled already.
      */
     public static long getTimeoutAfter(Notification notification) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return notification.getTimeoutAfter();
         } else {
             return 0;
@@ -4447,7 +4446,7 @@
      * {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}.
      */
     public static int getBadgeIconType(Notification notification) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return notification.getBadgeIconType();
         } else {
             return BADGE_ICON_NONE;
@@ -4459,7 +4458,7 @@
      * notification supersedes, if any.
      */
     public static String getShortcutId(Notification notification) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return notification.getShortcutId();
         } else {
             return null;
@@ -4472,7 +4471,7 @@
      * {@link #GROUP_ALERT_SUMMARY}.
      */
     public static int getGroupAlertBehavior(Notification notification) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return notification.getGroupAlertBehavior();
         } else {
             return GROUP_ALERT_ALL;
diff --git a/compat/java/android/support/v4/content/ContextCompat.java b/compat/java/android/support/v4/content/ContextCompat.java
index 2790234..9d8f551 100644
--- a/compat/java/android/support/v4/content/ContextCompat.java
+++ b/compat/java/android/support/v4/content/ContextCompat.java
@@ -30,7 +30,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.app.ActivityOptionsCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.os.EnvironmentCompat;
 import android.util.Log;
 import android.util.TypedValue;
@@ -557,7 +556,7 @@
      * @see Context#startService()
      */
     public static void startForegroundService(Context context, Intent intent) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             context.startForegroundService(intent);
         } else {
             // Pre-O behavior.
diff --git a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
index ecc9344..9cfc3d3 100644
--- a/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
+++ b/compat/java/android/support/v4/content/pm/ShortcutManagerCompat.java
@@ -24,11 +24,11 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutManager;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.os.BuildCompat;
 import android.text.TextUtils;
 
 /**
@@ -51,7 +51,7 @@
      * {@code false} otherwise
      */
     public static boolean isRequestPinShortcutSupported(@NonNull Context context) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return context.getSystemService(ShortcutManager.class).isRequestPinShortcutSupported();
         }
 
@@ -88,7 +88,7 @@
      */
     public static boolean requestPinShortcut(@NonNull final Context context,
             @NonNull ShortcutInfoCompat shortcut, @Nullable final IntentSender callback) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return context.getSystemService(ShortcutManager.class).requestPinShortcut(
                     shortcut.toShortcutInfo(), callback);
         }
@@ -132,7 +132,7 @@
     public static Intent createShortcutResultIntent(@NonNull Context context,
             @NonNull ShortcutInfoCompat shortcut) {
         Intent result = null;
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             result = context.getSystemService(ShortcutManager.class)
                     .createShortcutResultIntent(shortcut.toShortcutInfo());
         }
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompat.java b/compat/java/android/support/v4/graphics/TypefaceCompat.java
index e9b2edd..f65d585 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompat.java
@@ -22,6 +22,7 @@
 import android.content.res.Resources;
 import android.graphics.Typeface;
 import android.net.Uri;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
@@ -31,8 +32,10 @@
 import android.support.v4.provider.FontsContractCompat;
 import android.support.v4.provider.FontsContractCompat.FontInfo;
 import android.support.v4.util.LruCache;
+import android.util.Log;
 import android.widget.TextView;
 
+import java.io.File;
 import java.nio.ByteBuffer;
 import java.util.Map;
 
@@ -42,8 +45,22 @@
  */
 @RestrictTo(LIBRARY_GROUP)
 public class TypefaceCompat {
-    // TODO(nona): Introduce API 24 implementation.
-    private static final TypefaceCompatImpl sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
+    private static final String TAG = "TypefaceCompat";
+
+    private static final TypefaceCompatImpl sTypefaceCompatImpl;
+    static {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
+        } else {
+            if (!TypefaceCompatApi24Impl.isUsable()) {
+                Log.w(TAG, "Unable to collect necessary private methods."
+                        + "Fallback to legacy implementation.");
+                sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
+            } else {
+                sTypefaceCompatImpl = new TypefaceCompatApi24Impl();
+            }
+        }
+    }
 
     /**
      * Cache for Typeface objects dynamically loaded from assets.
@@ -51,13 +68,9 @@
     private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
 
     interface TypefaceCompatImpl {
-        // Create Typeface from font file in res/font directory.
-        Typeface createFromResourcesFontFile(Context context, Resources resources, int id,
-                int style);
-
         // Create Typeface from XML which root node is "font-family"
         Typeface createFromFontFamilyFilesResourceEntry(
-                Context context, FontFamilyFilesResourceEntry entry, Resources resources, int id,
+                Context context, FontFamilyFilesResourceEntry entry, Resources resources,
                 int style);
 
         Typeface createTypeface(Context context, @NonNull FontInfo[] fonts,
@@ -103,7 +116,7 @@
                     providerEntry.getTimeout(), style);
         } else {
             typeface = sTypefaceCompatImpl.createFromFontFamilyFilesResourceEntry(
-                    context, (FontFamilyFilesResourceEntry) entry, resources, id, style);
+                    context, (FontFamilyFilesResourceEntry) entry, resources, style);
         }
         if (typeface != null) {
             sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
@@ -117,12 +130,27 @@
     @Nullable
     public static Typeface createFromResourcesFontFile(
             Context context, Resources resources, int id, int style) {
-        Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile(
-                context, resources, id, style);
-        if (typeface != null) {
-            sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
+        final File tmpFile = TypefaceCompatUtil.getTempFile(context);
+        if (tmpFile == null) {
+            return null;
         }
-        return typeface;
+        try {
+            if (!TypefaceCompatUtil.copyToFile(tmpFile, resources, id)) {
+                return null;
+            }
+            Typeface typeface = Typeface.createFromFile(tmpFile.getPath());
+            if (typeface != null) {
+                sTypefaceCache.put(createResourceUid(resources, id, style), typeface);
+            }
+            return typeface;
+        } catch (RuntimeException e) {
+            // This was thrown from Typeface.createFromFile when a Typeface could not be loaded.
+            // such as due to an invalid ttf or unreadable file. We don't want to throw that
+            // exception anymore.
+            return null;
+        } finally {
+            tmpFile.delete();
+        }
     }
 
     /**
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java b/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
new file mode 100644
index 0000000..9bf0858
--- /dev/null
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
+import android.support.v4.content.res.FontResourcesParserCompat.FontFileResourceEntry;
+import android.support.v4.provider.FontsContractCompat.FontInfo;
+import android.util.Log;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Implementation of the Typeface compat methods for API 24 and above.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+@RequiresApi(24)
+class TypefaceCompatApi24Impl implements TypefaceCompat.TypefaceCompatImpl {
+    private static final String TAG = "TypefaceCompatApi24Impl";
+
+    private static final String FONT_FAMILY_CLASS = "android.graphics.FontFamily";
+    private static final String ADD_FONT_WEIGHT_STYLE_METHOD = "addFontWeightStyle";
+    private static final String CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD =
+            "createFromFamiliesWithDefault";
+    private static final Class sFontFamily;
+    private static final Constructor sFontFamilyCtor;
+    private static final Method sAddFontWeightStyle;
+    private static final Method sCreateFromFamiliesWithDefault;
+
+    static {
+        Class fontFamilyClass;
+        Constructor fontFamilyCtor;
+        Method addFontMethod;
+        Method createFromFamiliesWithDefaultMethod;
+        try {
+            fontFamilyClass = Class.forName(FONT_FAMILY_CLASS);
+            fontFamilyCtor = fontFamilyClass.getConstructor();
+            addFontMethod = fontFamilyClass.getMethod(ADD_FONT_WEIGHT_STYLE_METHOD,
+                    ByteBuffer.class, Integer.TYPE, List.class, Integer.TYPE, Boolean.TYPE);
+            Object familyArray = Array.newInstance(fontFamilyClass, 1);
+            createFromFamiliesWithDefaultMethod =
+                    Typeface.class.getMethod(CREATE_FROM_FAMILIES_WITH_DEFAULT_METHOD,
+                          familyArray.getClass());
+        } catch (ClassNotFoundException | NoSuchMethodException e) {
+            Log.e(TAG, e.getClass().getName(), e);
+            fontFamilyClass = null;
+            fontFamilyCtor = null;
+            addFontMethod = null;
+            createFromFamiliesWithDefaultMethod = null;
+        }
+        sFontFamilyCtor = fontFamilyCtor;
+        sFontFamily = fontFamilyClass;
+        sAddFontWeightStyle = addFontMethod;
+        sCreateFromFamiliesWithDefault = createFromFamiliesWithDefaultMethod;
+    }
+
+    /**
+     * Returns true if API24 implementation is usable.
+     */
+    public static boolean isUsable() {
+        return sAddFontWeightStyle != null;
+    }
+
+    private static Object newFamily() {
+        try {
+            return sFontFamilyCtor.newInstance();
+        } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static boolean addFontWeightStyle(Object family, ByteBuffer buffer, int ttcIndex,
+            int weight, boolean style) {
+        try {
+            final Boolean result = (Boolean) sAddFontWeightStyle.invoke(
+                    family, buffer, ttcIndex, null /* variation axis */, weight, style);
+            return result.booleanValue();
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Typeface createFromFamiliesWithDefault(Object family) {
+        try {
+            Object familyArray = Array.newInstance(sFontFamily, 1);
+            Array.set(familyArray, 0, family);
+            return (Typeface) sCreateFromFamiliesWithDefault.invoke(
+                    null /* static method */, familyArray);
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public Typeface createTypeface(Context context, @NonNull FontInfo[] fonts,
+            Map<Uri, ByteBuffer> uriBuffer) {
+        Object family = newFamily();
+        for (final FontInfo font : fonts) {
+            if (!addFontWeightStyle(family, uriBuffer.get(font.getUri()), font.getTtcIndex(),
+                    font.getWeight(), font.isItalic())) {
+                return null;
+            }
+        }
+        return createFromFamiliesWithDefault(family);
+    }
+
+    @Override
+    public Typeface createFromFontFamilyFilesResourceEntry(Context context,
+            FontFamilyFilesResourceEntry entry, Resources resources, int style) {
+        Object family = newFamily();
+        for (final FontFileResourceEntry e : entry.getEntries()) {
+            final ByteBuffer buffer =
+                    TypefaceCompatUtil.copyToDirectBuffer(context, resources, e.getResourceId());
+            // TODO: support ttc index.
+            if (!addFontWeightStyle(family, buffer, 0, e.getWeight(), e.isItalic())) {
+                return null;
+            }
+        }
+        return createFromFamiliesWithDefault(family);
+    }
+}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java b/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
index 86bcae8..0dad80a 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatBaseImpl.java
@@ -29,13 +29,8 @@
 import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
 import android.support.v4.content.res.FontResourcesParserCompat.FontFileResourceEntry;
 import android.support.v4.provider.FontsContractCompat.FontInfo;
-import android.util.Log;
 
-import java.io.Closeable;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.Map;
 
@@ -59,90 +54,22 @@
         Typeface typeface = null;
         FontInfo font = fonts[0];
         ByteBuffer buffer = uriBuffer.get(font.getUri());
-        File tmpFile = copyToCacheFile(context, buffer);
-        if (tmpFile != null) {
-            try {
-                typeface = Typeface.createFromFile(tmpFile.getPath());
-            } catch (RuntimeException e) {
-                // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
-                // such as due to an invalid ttf or unreadable file. We don't want to throw that
-                // exception anymore.
+        final File tmpFile = TypefaceCompatUtil.getTempFile(context);
+        if (tmpFile == null) {
+            return null;
+        }
+        try {
+            if (!TypefaceCompatUtil.copyToFile(tmpFile, buffer)) {
                 return null;
-            } finally {
-                tmpFile.delete();
             }
-        }
-        return typeface;
-    }
-
-    private static File copyToCacheFile(Context context, final InputStream is) {
-        FileOutputStream fos = null;
-        File cacheFile;
-        try {
-            cacheFile = new File(context.getCacheDir(),
-                    CACHE_FILE_PREFIX + Thread.currentThread().getId());
-            fos = new FileOutputStream(cacheFile, false);
-
-            byte[] buffer = new byte[1024];
-            int readLen;
-            while ((readLen = is.read(buffer)) != -1) {
-                fos.write(buffer, 0, readLen);
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Error copying font file descriptor to temp local file.", e);
+            return Typeface.createFromFile(tmpFile.getPath());
+        } catch (RuntimeException e) {
+            // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
+            // such as due to an invalid ttf or unreadable file. We don't want to throw that
+            // exception anymore.
             return null;
         } finally {
-            closeQuietly(is);
-            closeQuietly(fos);
-        }
-        return cacheFile;
-    }
-
-    private static File copyToCacheFile(Context context, final ByteBuffer is) {
-        FileOutputStream fos = null;
-        File cacheFile;
-        try {
-            cacheFile = new File(context.getCacheDir(),
-                    CACHE_FILE_PREFIX + Thread.currentThread().getId());
-            fos = new FileOutputStream(cacheFile, false);
-
-            byte[] buffer = new byte[1024];
-            while (is.hasRemaining()) {
-                int len = Math.min(1024, is.remaining());
-                is.get(buffer, 0, len);
-                fos.write(buffer, 0, len);
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Error copying font file descriptor to temp local file.", e);
-            return null;
-        } finally {
-            closeQuietly(fos);
-        }
-        return cacheFile;
-    }
-
-    private static void closeQuietly(InputStream is) {
-        if (is != null) {
-            try {
-                is.close();
-            } catch (IOException io) {
-                Log.e(TAG, "Error closing input stream", io);
-            }
-        }
-    }
-
-    @Nullable
-    @Override
-    public Typeface createFromResourcesFontFile(Context context, Resources resources, int id,
-            int style) {
-        InputStream is = null;
-        try {
-            is = resources.openRawResource(id);
-            return createTypeface(context, resources, is);
-        } catch (IOException e) {
-            return null;
-        } finally {
-            closeQuietly(is);
+            tmpFile.delete();
         }
     }
 
@@ -166,52 +93,13 @@
     @Nullable
     @Override
     public Typeface createFromFontFamilyFilesResourceEntry(Context context,
-            FontFamilyFilesResourceEntry entry, Resources resources, int id, int style) {
+            FontFamilyFilesResourceEntry entry, Resources resources, int style) {
         FontFileResourceEntry best = findBestEntry(
                 entry, ((style & Typeface.BOLD) == 0) ? 400 : 700, (style & Typeface.ITALIC) != 0);
         if (best == null) {
             return null;
         }
-
-        InputStream is = null;
-        try {
-            is = resources.openRawResource(best.getResourceId());
-            return createTypeface(context, resources, is);
-        } catch (IOException e) {
-            // This is fine. The resource can be string type which indicates a name of Typeface.
-        } finally {
-            closeQuietly(is);
-        }
-        return null;
-    }
-
-    // Caller must close "is"
-    Typeface createTypeface(Context context, Resources resources, InputStream is)
-            throws IOException {
-        File tmpFile = copyToCacheFile(context, is);
-        if (tmpFile != null) {
-            try {
-                return Typeface.createFromFile(tmpFile.getPath());
-            } catch (RuntimeException e) {
-                // This was thrown from Typeface.createFromFile when a Typeface could not be loaded,
-                // such as due to an invalid ttf or unreadable file. We don't want to throw that
-                // exception anymore.
-                android.util.Log.e(TAG, "Failed to create font", e);
-                return null;
-            } finally {
-                tmpFile.delete();
-            }
-        }
-        return null;
-    }
-
-    static void closeQuietly(Closeable stream) {
-        if (stream != null) {
-            try {
-                stream.close();
-            } catch (IOException io) {
-                Log.e(TAG, "Error closing stream", io);
-            }
-        }
+        return TypefaceCompat.createFromResourcesFontFile(
+                context, resources, best.getResourceId(), style);
     }
 }
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java b/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java
new file mode 100644
index 0000000..5539c35
--- /dev/null
+++ b/compat/java/android/support/v4/graphics/TypefaceCompatUtil.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Process;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.RestrictTo;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Utility methods for TypefaceCompat.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+class TypefaceCompatUtil {
+    private static final String TAG = "TypefaceCompatUtil";
+
+    private TypefaceCompatUtil() {}  // Do not instantiate.
+
+    private static final String CACHE_FILE_PREFIX = ".font";
+
+    /**
+     * Creates a temp file.
+     *
+     * Returns null if failed to create temp file.
+     */
+    public static File getTempFile(Context context) {
+        final String prefix = CACHE_FILE_PREFIX + Process.myPid() + "-" + Process.myTid() + "-";
+        for (int i = 0; i < 100; ++i) {
+            final File file = new File(context.getCacheDir(), prefix + i);
+            try {
+                if (file.createNewFile()) {
+                    return file;
+                }
+            } catch (IOException e) {
+                // ignore. Try next file.
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Copy the file contents to the direct byte buffer.
+     */
+    @RequiresApi(19)
+    private static ByteBuffer mmap(File file) {
+        try (FileInputStream fis = new FileInputStream(file)) {
+            FileChannel channel = fis.getChannel();
+            final long size = channel.size();
+            return channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Copy the resource contents to the direct byte buffer.
+     */
+    @RequiresApi(19)
+    public static ByteBuffer copyToDirectBuffer(Context context, Resources res, int id) {
+        File tmpFile = getTempFile(context);
+        if (tmpFile == null) {
+            return null;
+        }
+        try {
+            if (!copyToFile(tmpFile, res, id)) {
+                return null;
+            }
+            return mmap(tmpFile);
+        } finally {
+            tmpFile.delete();
+        }
+    }
+
+    /**
+     * Helper class for reading ByteBuffer as InputStream.
+     */
+    private static class ByteBufferInputStream extends InputStream {
+        private ByteBuffer mBuf;
+
+        ByteBufferInputStream(ByteBuffer buf) {
+            mBuf = buf;
+        }
+
+        @Override
+        public int read() {
+            if (!mBuf.hasRemaining()) {
+                return -1;
+            }
+            return mBuf.get() & 0xFF;
+        }
+
+        @Override
+        public int read(byte[] bytes, int off, int len) {
+            if (!mBuf.hasRemaining()) {
+                return -1;
+            }
+            len = Math.min(len, mBuf.remaining());
+            mBuf.get(bytes, off, len);
+            return len;
+        }
+    }
+
+    /**
+     * Copy the buffer contents to file.
+     */
+    public static boolean copyToFile(File file, ByteBuffer buffer) {
+        return copyToFile(file, new ByteBufferInputStream(buffer));
+    }
+
+    /**
+     * Copy the input stream contents to file.
+     */
+    public static boolean copyToFile(File file, InputStream is) {
+        FileOutputStream os = null;
+        try {
+            os = new FileOutputStream(file, false);
+            byte[] buffer = new byte[1024];
+            int readLen;
+            while ((readLen = is.read(buffer)) != -1) {
+                os.write(buffer, 0, readLen);
+            }
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "Error copying resource contents to temp file: " + e.getMessage());
+            return false;
+        } finally {
+            closeQuietly(os);
+        }
+    }
+
+    /**
+     * Copy the resource contents to file.
+     */
+    public static boolean copyToFile(File file, Resources res, int id) {
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+            return copyToFile(file, is);
+        } finally {
+            closeQuietly(is);
+        }
+    }
+
+    public static void closeQuietly(Closeable c) {
+        if (c != null) {
+            try {
+                c.close();
+            } catch (IOException e) {
+            }
+        }
+    }
+}
diff --git a/compat/java/android/support/v4/graphics/drawable/IconCompat.java b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
index c820366..c268d8b 100644
--- a/compat/java/android/support/v4/graphics/drawable/IconCompat.java
+++ b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
@@ -34,7 +34,6 @@
 import android.support.annotation.DrawableRes;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
 
 /**
  * Helper for accessing features in {@link android.graphics.drawable.Icon}
@@ -186,7 +185,7 @@
             case TYPE_BITMAP:
                 return Icon.createWithBitmap((Bitmap) mObj1);
             case TYPE_ADAPTIVE_BITMAP:
-                if (BuildCompat.isAtLeastO()) {
+                if (Build.VERSION.SDK_INT >= 26) {
                     return Icon.createWithAdaptiveBitmap((Bitmap) mObj1);
                 } else {
                     return Icon.createWithBitmap(createLegacyIconFromAdaptiveIcon((Bitmap) mObj1));
diff --git a/compat/java/android/support/v4/os/LocaleHelper.java b/compat/java/android/support/v4/os/LocaleHelper.java
index 539106c..f6fe7da 100644
--- a/compat/java/android/support/v4/os/LocaleHelper.java
+++ b/compat/java/android/support/v4/os/LocaleHelper.java
@@ -62,7 +62,7 @@
         StringBuilder buf = new StringBuilder();
         buf.append(locale.getLanguage());
         final String country = locale.getCountry();
-        if (country != null && !country.equals("")) {
+        if (country != null && !country.isEmpty()) {
             buf.append("-");
             buf.append(locale.getCountry());
         }
diff --git a/compat/java/android/support/v4/os/LocaleListCompat.java b/compat/java/android/support/v4/os/LocaleListCompat.java
index 1185e98..d4a32f2 100644
--- a/compat/java/android/support/v4/os/LocaleListCompat.java
+++ b/compat/java/android/support/v4/os/LocaleListCompat.java
@@ -285,7 +285,7 @@
      */
     @NonNull
     public static LocaleListCompat forLanguageTags(@Nullable String list) {
-        if (list == null || list.equals("")) {
+        if (list == null || list.isEmpty()) {
             return getEmptyLocaleList();
         } else {
             final String[] tags = list.split(",");
diff --git a/compat/java/android/support/v4/os/LocaleListHelper.java b/compat/java/android/support/v4/os/LocaleListHelper.java
index 133ecfe..cfb24fb 100644
--- a/compat/java/android/support/v4/os/LocaleListHelper.java
+++ b/compat/java/android/support/v4/os/LocaleListHelper.java
@@ -271,7 +271,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @NonNull
     static LocaleListHelper forLanguageTags(@Nullable String list) {
-        if (list == null || list.equals("")) {
+        if (list == null || list.isEmpty()) {
             return getEmptyLocaleList();
         } else {
             final String[] tags = list.split(",");
diff --git a/compat/java/android/support/v4/provider/FontsContractCompat.java b/compat/java/android/support/v4/provider/FontsContractCompat.java
index ba44019..fc00d50 100644
--- a/compat/java/android/support/v4/provider/FontsContractCompat.java
+++ b/compat/java/android/support/v4/provider/FontsContractCompat.java
@@ -19,6 +19,7 @@
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 import static android.support.v4.content.res.FontResourcesParserCompat.FetchStrategy;
 
+import android.annotation.SuppressLint;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
@@ -699,6 +700,8 @@
         }
 
         List<byte[]> signatures;
+        // We correctly check all signatures returned, as advised in the lint error.
+        @SuppressLint("PackageManagerGetSignatures")
         PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName,
                 PackageManager.GET_SIGNATURES);
         signatures = convertToByteArrayList(packageInfo.signatures);
diff --git a/compat/java/android/support/v4/text/util/LinkifyCompat.java b/compat/java/android/support/v4/text/util/LinkifyCompat.java
index d242780..23b3e49 100644
--- a/compat/java/android/support/v4/text/util/LinkifyCompat.java
+++ b/compat/java/android/support/v4/text/util/LinkifyCompat.java
@@ -18,6 +18,7 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
+import android.os.Build;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -96,6 +97,9 @@
      *  @return True if at least one link is found and applied.
      */
     public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Linkify.addLinks(text, mask);
+        }
         if (mask == 0) {
             return false;
         }
@@ -157,6 +161,9 @@
      *  @return True if at least one link is found and applied.
      */
     public static final boolean addLinks(@NonNull TextView text, @LinkifyMask int mask) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Linkify.addLinks(text, mask);
+        }
         if (mask == 0) {
             return false;
         }
@@ -197,6 +204,10 @@
      */
     public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
             @Nullable String scheme) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            Linkify.addLinks(text, pattern, scheme);
+            return;
+        }
         addLinks(text, pattern, scheme, null, null, null);
     }
 
@@ -217,6 +228,10 @@
     public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
             @Nullable String scheme, @Nullable MatchFilter matchFilter,
             @Nullable TransformFilter transformFilter) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            Linkify.addLinks(text, pattern, scheme, matchFilter, transformFilter);
+            return;
+        }
         addLinks(text, pattern, scheme, null, matchFilter, transformFilter);
     }
 
@@ -238,8 +253,12 @@
      *  @param transformFilter Filter to allow the client code to update the link found.
      */
     public static final void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
-            @Nullable  String defaultScheme, @Nullable String[] schemes,
+            @Nullable String defaultScheme, @Nullable String[] schemes,
             @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            Linkify.addLinks(text, pattern, defaultScheme, schemes, matchFilter, transformFilter);
+            return;
+        }
         SpannableString spannable = SpannableString.valueOf(text.getText());
 
         boolean linksAdded = addLinks(spannable, pattern, defaultScheme, schemes, matchFilter,
@@ -261,6 +280,9 @@
      */
     public static final boolean addLinks(@NonNull Spannable text, @NonNull Pattern pattern,
             @Nullable String scheme) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Linkify.addLinks(text, pattern, scheme);
+        }
         return addLinks(text, pattern, scheme, null, null, null);
     }
 
@@ -282,6 +304,9 @@
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable String scheme, @Nullable MatchFilter matchFilter,
             @Nullable TransformFilter transformFilter) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Linkify.addLinks(spannable, pattern, scheme, matchFilter, transformFilter);
+        }
         return addLinks(spannable, pattern, scheme, null, matchFilter,
                 transformFilter);
     }
@@ -305,6 +330,10 @@
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable  String defaultScheme, @Nullable String[] schemes,
             @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Linkify.addLinks(spannable, pattern, defaultScheme, schemes, matchFilter,
+                    transformFilter);
+        }
         final String[] schemesCopy;
         if (defaultScheme == null) defaultScheme = "";
         if (schemes == null || schemes.length < 1) {
diff --git a/compat/java/android/support/v4/view/MenuItemCompat.java b/compat/java/android/support/v4/view/MenuItemCompat.java
index 649c413..d7e96cc 100644
--- a/compat/java/android/support/v4/view/MenuItemCompat.java
+++ b/compat/java/android/support/v4/view/MenuItemCompat.java
@@ -19,9 +19,9 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.support.annotation.RequiresApi;
 import android.support.v4.internal.view.SupportMenuItem;
-import android.support.v4.os.BuildCompat;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -274,7 +274,7 @@
      */
     static final MenuVersionImpl IMPL;
     static {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             IMPL = new MenuItemCompatApi26Impl();
         } else {
             IMPL = new MenuItemCompatBaseImpl();
diff --git a/compat/java/android/support/v4/view/ViewCompat.java b/compat/java/android/support/v4/view/ViewCompat.java
index efbf848..a4035b2 100644
--- a/compat/java/android/support/v4/view/ViewCompat.java
+++ b/compat/java/android/support/v4/view/ViewCompat.java
@@ -36,7 +36,6 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
 import android.util.Log;
@@ -1576,7 +1575,7 @@
 
     static final ViewCompatBaseImpl IMPL;
     static {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             IMPL = new ViewCompatApi26Impl();
         } else if (Build.VERSION.SDK_INT >= 24) {
             IMPL = new ViewCompatApi24Impl();
diff --git a/compat/java/android/support/v4/view/ViewConfigurationCompat.java b/compat/java/android/support/v4/view/ViewConfigurationCompat.java
index 683a380..4ae2260 100644
--- a/compat/java/android/support/v4/view/ViewConfigurationCompat.java
+++ b/compat/java/android/support/v4/view/ViewConfigurationCompat.java
@@ -17,8 +17,8 @@
 package android.support.v4.view;
 
 import android.content.Context;
+import android.os.Build;
 import android.support.annotation.NonNull;
-import android.support.v4.os.BuildCompat;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.ViewConfiguration;
@@ -37,7 +37,7 @@
     private static Method sGetScaledScrollFactorMethod;
 
     static {
-        if (android.os.Build.VERSION.SDK_INT >= 25 && !BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT == 25) {
             try {
                 sGetScaledScrollFactorMethod =
                         ViewConfiguration.class.getDeclaredMethod("getScaledScrollFactor");
@@ -79,7 +79,7 @@
      */
     public static float getScaledHorizontalScrollFactor(@NonNull ViewConfiguration config,
             @NonNull Context context) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return config.getScaledHorizontalScrollFactor();
         } else {
             return getLegacyScrollFactor(config, context);
@@ -96,7 +96,7 @@
      */
     public static float getScaledVerticalScrollFactor(@NonNull ViewConfiguration config,
             @NonNull Context context) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return config.getScaledVerticalScrollFactor();
         } else {
             return getLegacyScrollFactor(config, context);
diff --git a/compat/tests/assets/fonts/large_a.ttf b/compat/tests/assets/fonts/large_a.ttf
new file mode 100644
index 0000000..0e778b6
--- /dev/null
+++ b/compat/tests/assets/fonts/large_a.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_a.ttx b/compat/tests/assets/fonts/large_a.ttx
new file mode 100644
index 0000000..c453414
--- /dev/null
+++ b/compat/tests/assets/fonts/large_a.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="3em" />
+      <map code="0x0062" name="1em" />
+      <map code="0x0063" name="1em" />
+      <map code="0x0064" name="1em" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+      Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_a.ttx.
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_b.ttf b/compat/tests/assets/fonts/large_b.ttf
new file mode 100644
index 0000000..b8ce6ce
--- /dev/null
+++ b/compat/tests/assets/fonts/large_b.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_b.ttx b/compat/tests/assets/fonts/large_b.ttx
new file mode 100644
index 0000000..0274e9c
--- /dev/null
+++ b/compat/tests/assets/fonts/large_b.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="1em" />
+      <map code="0x0062" name="3em" />
+      <map code="0x0063" name="1em" />
+      <map code="0x0064" name="1em" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+      Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_b.ttx.
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_c.ttf b/compat/tests/assets/fonts/large_c.ttf
new file mode 100644
index 0000000..dd5fa50
--- /dev/null
+++ b/compat/tests/assets/fonts/large_c.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_c.ttx b/compat/tests/assets/fonts/large_c.ttx
new file mode 100644
index 0000000..d3657b1
--- /dev/null
+++ b/compat/tests/assets/fonts/large_c.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="1em" />
+      <map code="0x0062" name="1em" />
+      <map code="0x0063" name="3em" />
+      <map code="0x0064" name="1em" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+      Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_c.ttx.
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/compat/tests/assets/fonts/large_d.ttf b/compat/tests/assets/fonts/large_d.ttf
new file mode 100644
index 0000000..b791100
--- /dev/null
+++ b/compat/tests/assets/fonts/large_d.ttf
Binary files differ
diff --git a/compat/tests/assets/fonts/large_d.ttx b/compat/tests/assets/fonts/large_d.ttx
new file mode 100644
index 0000000..12f668c
--- /dev/null
+++ b/compat/tests/assets/fonts/large_d.ttx
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="1em" />
+      <map code="0x0062" name="1em" />
+      <map code="0x0063" name="1em" />
+      <map code="0x0064" name="3em" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
+      Source code is available at platform/frameworks/support/compat/tests/assets/fonts/large_d.ttx.
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
new file mode 100644
index 0000000..dc0650b
--- /dev/null
+++ b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.graphics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.support.compat.test.R;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
+import android.support.testutils.PollingCheck;
+import android.support.v4.content.res.FontResourcesParserCompat;
+import android.support.v4.content.res.FontResourcesParserCompat.FamilyResourceEntry;
+import android.support.v4.content.res.FontResourcesParserCompat.ProviderResourceEntry;
+import android.support.v4.provider.FontRequest;
+import android.support.v4.provider.MockFontProvider;
+import android.widget.TextView;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@SdkSuppress(maxSdkVersion = 25)  // on API 26, use platform implementation.
+@SmallTest
+public class TypefaceCompatTest {
+    private static final String AUTHORITY = "android.provider.fonts.font";
+    private static final String PACKAGE = "android.support.compat.test";
+
+    public Context mContext;
+    public Resources mResources;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mResources = mContext.getResources();
+        MockFontProvider.prepareFontFiles(mContext);
+    }
+
+    @After
+    public void tearDown() {
+        MockFontProvider.cleanUpFontFiles(mContext);
+    }
+
+    // Signature to be used for authentication to access content provider.
+    // In this test case, the content provider and consumer live in the same package, self package's
+    // signature works.
+    private static final List<List<byte[]>> SIGNATURE;
+    static {
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        try {
+            PackageManager manager = context.getPackageManager();
+            PackageInfo info = manager.getPackageInfo(
+                    context.getPackageName(), PackageManager.GET_SIGNATURES);
+            ArrayList<byte[]> out = new ArrayList<>();
+            for (Signature sig : info.signatures) {
+                out.add(sig.toByteArray());
+            }
+            SIGNATURE = new ArrayList<>();
+            SIGNATURE.add(out);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Helper method to get the used font resource id by typeface.
+     *
+     * If the typeface is created from one of the R.font.large_a, R.font.large_b, R.font.large_c or
+     * R.font.large_d resource, this method returns the resource id used by the typeface.
+     */
+    private static int getSelectedFontResourceId(Typeface typeface) {
+        // The glyph for "a" in R.font.large_a font has a 3em width and glyph for "b", "c" and "d"
+        // have 1em width. Similarly, The glyph for "b" in R.font.large_b font, the glyph for "c"
+        // in R.font.large_c font, the glyph for "d" in R.font.large_d font has 3em width and the
+        // glyph for the rest characters have 1em. Thus we can get the resource id of the source
+        // font file by comparing width of "a", "b", "c" and "d".
+        Paint p = new Paint();
+        p.setTypeface(typeface);
+        final int[] ids = { R.font.large_a, R.font.large_b, R.font.large_c, R.font.large_d };
+        final float[] widths = {
+            p.measureText("a"), p.measureText("b"), p.measureText("c"), p.measureText("d")
+        };
+
+        int maxIndex = Integer.MIN_VALUE;
+        float maxValue = Float.MIN_VALUE;
+        for (int i = 0; i < widths.length; ++i) {
+            if (maxValue < widths[i]) {
+                maxIndex = i;
+                maxValue = widths[i];
+            }
+        }
+        return ids[maxIndex];
+    }
+
+    /**
+     * Helper method to obtain ProviderResourceEntry with overwriting correct signatures.
+     */
+    private ProviderResourceEntry getProviderResourceEntry(int id) {
+        final ProviderResourceEntry entry;
+        try {
+            entry = (ProviderResourceEntry) FontResourcesParserCompat.parse(
+                    mResources.getXml(id), mResources);
+        } catch (XmlPullParserException | IOException e) {
+            throw new RuntimeException(e);
+        }
+        final FontRequest parsedRequest = entry.getRequest();
+        final FontRequest request = new FontRequest(parsedRequest.getProviderAuthority(),
+                parsedRequest.getProviderPackage(), parsedRequest.getQuery(), SIGNATURE);
+        return new ProviderResourceEntry(request, entry.getFetchStrategy(), entry.getTimeout());
+    }
+
+    @Test
+    public void testCreateFromResourcesFamilyXml_resourceFont_syncloading() throws Exception {
+        Typeface typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext,
+                getProviderResourceEntry(R.font.styletest_sync_providerfont), mResources,
+                R.font.styletest_sync_providerfont, Typeface.NORMAL, null /* TextView */);
+        // TODO: Add support of styled font selection from family result.
+        assertNotNull(typeface);
+    }
+
+    @Test
+    public void testCreateFromResourcesFamilyXml_resourceFont_asyncloading() throws Exception {
+        Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+        final TextView textView = new TextView(mContext);
+        inst.runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                TypefaceCompat.createFromResourcesFamilyXml(mContext,
+                        getProviderResourceEntry(R.font.styletest_async_providerfont), mResources,
+                        R.font.styletest_sync_providerfont, Typeface.NORMAL, textView);
+            }
+        });
+        PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
+            @Override
+            public boolean canProceed() {
+                return textView.getTypeface() != null;
+            }
+        });
+        // TODO: Add support of styled font selection from family result.
+        assertNotNull(textView.getTypeface());
+    }
+
+    @Test
+    public void testCreateFromResourcesFamilyXml_resourceFont() throws Exception {
+        final FamilyResourceEntry entry = FontResourcesParserCompat.parse(
+                mResources.getXml(R.font.styletestfont), mResources);
+        Typeface typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+                R.font.styletestfont, Typeface.NORMAL, null /* text view */);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.styletestfont, Typeface.NORMAL));
+        typeface = Typeface.create(typeface, Typeface.NORMAL);
+        // styletestfont has a node of fontStyle="normal" fontWeight="400" font="@font/large_a".
+        assertEquals(R.font.large_a, getSelectedFontResourceId(typeface));
+
+        typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+                R.font.styletestfont, Typeface.ITALIC, null);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.styletestfont, Typeface.ITALIC));
+        typeface = Typeface.create(typeface, Typeface.ITALIC);
+        // styletestfont has a node of fontStyle="italic" fontWeight="400" font="@font/large_b".
+        assertEquals(R.font.large_b, getSelectedFontResourceId(typeface));
+
+        typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+                R.font.styletestfont, Typeface.BOLD, null);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.styletestfont, Typeface.BOLD));
+        typeface = Typeface.create(typeface, Typeface.BOLD);
+        // styletestfont has a node of fontStyle="normal" fontWeight="700" font="@font/large_c".
+        assertEquals(R.font.large_c, getSelectedFontResourceId(typeface));
+
+        typeface = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry, mResources,
+                R.font.styletestfont, Typeface.BOLD_ITALIC, null);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.styletestfont, Typeface.BOLD_ITALIC));
+        typeface = Typeface.create(typeface, Typeface.BOLD_ITALIC);
+        // styletestfont has a node of fontStyle="italic" fontWeight="700" font="@font/large_d".
+        assertEquals(R.font.large_d, getSelectedFontResourceId(typeface));
+    }
+
+    @Test
+    public void testCreateFromResourcesFontFile() {
+        Typeface typeface = TypefaceCompat.createFromResourcesFontFile(
+                mContext, mResources, R.font.large_a, Typeface.NORMAL);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.large_a, Typeface.NORMAL));
+        assertEquals(R.font.large_a, getSelectedFontResourceId(typeface));
+
+        typeface = TypefaceCompat.createFromResourcesFontFile(
+                mContext, mResources, R.font.large_b, Typeface.NORMAL);
+        assertEquals(typeface, TypefaceCompat.findFromCache(
+                mResources, R.font.large_b, Typeface.NORMAL));
+        assertEquals(R.font.large_b, getSelectedFontResourceId(typeface));
+    }
+}
diff --git a/compat/tests/java/android/support/v4/provider/MockFontProvider.java b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
index 14b16a5..323dfe1 100644
--- a/compat/tests/java/android/support/v4/provider/MockFontProvider.java
+++ b/compat/tests/java/android/support/v4/provider/MockFontProvider.java
@@ -41,9 +41,13 @@
  */
 public class MockFontProvider extends ContentProvider {
     static final String[] FONT_FILES = {
-            "samplefont.ttf",
+            "samplefont.ttf", "large_a.ttf", "large_b.ttf", "large_c.ttf", "large_d.ttf"
     };
     private static final int SAMPLE_FONT_FILE_0_ID = 0;
+    private static final int LARGE_A_FILE_ID = 1;
+    private static final int LARGE_B_FILE_ID = 2;
+    private static final int LARGE_C_FILE_ID = 3;
+    private static final int LARGE_D_FILE_ID = 4;
 
     static final String SINGLE_FONT_FAMILY_QUERY = "singleFontFamily";
     static final String SINGLE_FONT_FAMILY2_QUERY = "singleFontFamily2";
@@ -54,6 +58,7 @@
     static final String NOT_FOUND_THIRD_QUERY = "notFoundThird";
     static final String NEGATIVE_ERROR_CODE_QUERY = "negativeCode";
     static final String MANDATORY_FIELDS_ONLY_QUERY = "mandatoryFields";
+    static final String STYLE_TEST_QUERY = "styleTest";
 
     static class Font {
         Font(int id, int fileId, int ttcIndex, String varSettings, int weight, int italic,
@@ -160,6 +165,17 @@
                         Columns.RESULT_CODE_OK, false),
         });
 
+        map.put(STYLE_TEST_QUERY, new Font[] {
+                new Font(id++, LARGE_A_FILE_ID, 0, null, 400, 0 /* normal */,
+                        Columns.RESULT_CODE_OK, true),
+                new Font(id++, LARGE_B_FILE_ID, 0, null, 400, 1 /* italic */,
+                        Columns.RESULT_CODE_OK, true),
+                new Font(id++, LARGE_C_FILE_ID, 0, null, 700, 0 /* normal */,
+                        Columns.RESULT_CODE_OK, true),
+                new Font(id++, LARGE_D_FILE_ID, 0, null, 700, 1 /* italic */,
+                        Columns.RESULT_CODE_OK, true),
+        });
+
         QUERY_MAP = Collections.unmodifiableMap(map);
     }
 
diff --git a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
index 51bb7d0..d79c789 100644
--- a/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
+++ b/compat/tests/java/android/support/v4/text/util/LinkifyCompatTest.java
@@ -245,12 +245,21 @@
             assertTrue(LinkifyCompat.addLinks(spannable, Linkify.ALL));
             URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
             assertEquals(3, spans.length);
-            assertEquals("tel:8005551233", spans[0].getURL());
-            assertEquals("mailto:800-555-1211@gmail.com", spans[1].getURL());
-            assertEquals("http://800-555-1222.com", spans[2].getURL());
+            assertTrue(containsUrl(spans, "tel:8005551233"));
+            assertTrue(containsUrl(spans, "mailto:800-555-1211@gmail.com"));
+            assertTrue(containsUrl(spans, "http://800-555-1222.com"));
         }
     }
 
+    private boolean containsUrl(URLSpan[] spans, String expectedValue) {
+        for (URLSpan span : spans) {
+            if (span.getURL().equals(expectedValue)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Test
     public void testAddLinks_addsLinksWhenDefaultSchemeIsNull() {
         Spannable spannable = new SpannableString("any https://android.com any android.com any");
diff --git a/compat/tests/res/font/dummyproviderfont.xml b/compat/tests/res/font/dummyproviderfont.xml
new file mode 100644
index 0000000..b0b41c3
--- /dev/null
+++ b/compat/tests/res/font/dummyproviderfont.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto"
+         android:fontProviderAuthority="android.provider.fonts.font"
+         android:fontProviderPackage="android.support.compat.test"
+         android:fontProviderQuery="styleTest"
+         app:fontProviderAuthority="android.provider.fonts.font"
+         app:fontProviderPackage="android.support.compat.test"
+         app:fontProviderQuery="styleTest" >
+</font-family>
diff --git a/compat/tests/res/font/large_a.ttf b/compat/tests/res/font/large_a.ttf
new file mode 100644
index 0000000..0e778b6
--- /dev/null
+++ b/compat/tests/res/font/large_a.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_b.ttf b/compat/tests/res/font/large_b.ttf
new file mode 100644
index 0000000..b8ce6ce
--- /dev/null
+++ b/compat/tests/res/font/large_b.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_c.ttf b/compat/tests/res/font/large_c.ttf
new file mode 100644
index 0000000..dd5fa50
--- /dev/null
+++ b/compat/tests/res/font/large_c.ttf
Binary files differ
diff --git a/compat/tests/res/font/large_d.ttf b/compat/tests/res/font/large_d.ttf
new file mode 100644
index 0000000..b791100
--- /dev/null
+++ b/compat/tests/res/font/large_d.ttf
Binary files differ
diff --git a/compat/tests/res/font/styletest_async_providerfont.xml b/compat/tests/res/font/styletest_async_providerfont.xml
new file mode 100644
index 0000000..8d934cb
--- /dev/null
+++ b/compat/tests/res/font/styletest_async_providerfont.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto"
+         android:fontProviderAuthority="android.support.provider.fonts.font"
+         android:fontProviderPackage="android.support.compat.test"
+         android:fontProviderQuery="styleTest"
+         app:fontProviderAuthority="android.support.provider.fonts.font"
+         app:fontProviderPackage="android.support.compat.test"
+         app:fontProviderQuery="styleTest"
+         app:fontProviderFetchStrategy="async">
+</font-family>
diff --git a/compat/tests/res/font/styletest_sync_providerfont.xml b/compat/tests/res/font/styletest_sync_providerfont.xml
new file mode 100644
index 0000000..4e9c7d6
--- /dev/null
+++ b/compat/tests/res/font/styletest_sync_providerfont.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto"
+         android:fontProviderAuthority="android.support.provider.fonts.font"
+         android:fontProviderPackage="android.support.compat.test"
+         android:fontProviderQuery="styleTest"
+         app:fontProviderAuthority="android.support.provider.fonts.font"
+         app:fontProviderPackage="android.support.compat.test"
+         app:fontProviderQuery="styleTest"
+         app:fontProviderFetchStrategy="blocking"
+         app:fontProviderFetchTimeout="forever">
+</font-family>
diff --git a/compat/tests/res/font/styletestfont.xml b/compat/tests/res/font/styletestfont.xml
new file mode 100644
index 0000000..f1326d5
--- /dev/null
+++ b/compat/tests/res/font/styletestfont.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto">
+    <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/large_a"
+          android:fontStyle="normal" android:fontWeight="400" android:font="@font/large_a" />
+    <font app:fontStyle="italic" app:fontWeight="400" app:font="@font/large_b"
+          android:fontStyle="italic" android:fontWeight="400" android:font="@font/large_b" />
+    <font app:fontStyle="normal" app:fontWeight="700" app:font="@font/large_c"
+          android:fontStyle="normal" android:fontWeight="700" android:font="@font/large_c" />
+    <font app:fontStyle="italic" app:fontWeight="700" app:font="@font/large_d"
+          android:fontStyle="italic" android:fontWeight="700" android:font="@font/large_d" />
+</font-family>
diff --git a/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java b/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
index 7826f86..a332b8a 100644
--- a/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
+++ b/core-ui/ics/android/support/v4/app/ActionBarDrawerToggleIcs.java
@@ -39,7 +39,7 @@
  */
 @RequiresApi(14)
 class ActionBarDrawerToggleIcs {
-    private static final String TAG = "ActionBarDrawerToggleHoneycomb";
+    private static final String TAG = "ActionBarDrawerToggle";
 
     private static final int[] THEME_ATTRS = new int[] {
             R.attr.homeAsUpIndicator
diff --git a/core-ui/java/android/support/v4/widget/Space.java b/core-ui/java/android/support/v4/widget/Space.java
index 4857479..77a2d2e 100644
--- a/core-ui/java/android/support/v4/widget/Space.java
+++ b/core-ui/java/android/support/v4/widget/Space.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.widget;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.util.AttributeSet;
@@ -48,6 +49,7 @@
      * @param canvas an unused parameter.
      */
     @Override
+    @SuppressLint("MissingSuperCall")
     public void draw(Canvas canvas) {
     }
 
diff --git a/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java b/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
index 983683f..25231aa 100644
--- a/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
+++ b/core-ui/java/android/support/v4/widget/SwipeRefreshLayout.java
@@ -527,7 +527,7 @@
      * @deprecated Use {@link #setColorSchemeResources(int...)}
      */
     @Deprecated
-    public void setColorScheme(@ColorInt int... colors) {
+    public void setColorScheme(@ColorRes int... colors) {
         setColorSchemeResources(colors);
     }
 
diff --git a/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java b/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
index 1544e76..855d01d 100644
--- a/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
+++ b/core-ui/tests/java/android/support/v4/view/BaseViewPagerTest.java
@@ -1076,7 +1076,7 @@
     }
 
     @Test
-    @MediumTest
+    @LargeTest
     public void testKeyboardNavigation() {
         ButtonPagerAdapter adapter = new ButtonPagerAdapter();
         adapter.add("Red", Color.RED);
diff --git a/design/src/android/support/design/widget/AppBarLayout.java b/design/src/android/support/design/widget/AppBarLayout.java
index 89fcf7c..d0e7027 100644
--- a/design/src/android/support/design/widget/AppBarLayout.java
+++ b/design/src/android/support/design/widget/AppBarLayout.java
@@ -34,7 +34,6 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.design.R;
 import android.support.v4.math.MathUtils;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.AbsSavedState;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.WindowInsetsCompat;
@@ -179,7 +178,7 @@
             ViewUtilsLollipop.setDefaultAppBarLayoutStateListAnimator(
                     this, a.getDimensionPixelSize(R.styleable.AppBarLayout_elevation, 0));
         }
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             // In O+, we have these values set in the style. Since there is no defStyleAttr for
             // AppBarLayout at the AppCompat level, check for these attributes here.
             if (a.hasValue(R.styleable.AppBarLayout_android_keyboardNavigationCluster)) {
diff --git a/development/refaster/IsAtLeastO.java b/development/refaster/IsAtLeastO.java
new file mode 100644
index 0000000..9198441
--- /dev/null
+++ b/development/refaster/IsAtLeastO.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+import android.os.Build.VERSION;
+import android.support.v4.os.BuildCompat;
+
+import com.google.errorprone.refaster.annotation.AfterTemplate;
+import com.google.errorprone.refaster.annotation.AlsoNegation;
+import com.google.errorprone.refaster.annotation.BeforeTemplate;
+
+/**
+ * Replace usages of BuildCompat.isAtLeastO() with SDK_INT check.
+ */
+public class IsAtLeastO {
+    @BeforeTemplate
+    boolean usingAtLeastO() {
+        return BuildCompat.isAtLeastO();
+    }
+
+    @AfterTemplate
+    @AlsoNegation
+    boolean optimizedMethod() {
+        return VERSION.SDK_INT >= 26;
+    }
+}
diff --git a/development/refaster/README b/development/refaster/README
new file mode 100644
index 0000000..daf8f0d
--- /dev/null
+++ b/development/refaster/README
@@ -0,0 +1,25 @@
+Author: aurimas@google.com
+Updated: 6/6/2017
+
+Instructions on how to compile and apply refaster rules to support library
+
+0. Download error-prone and refaster jars
+http://errorprone.info/docs/refaster will have up to date instructions
+
+1. Compile the refaster rule (in this example IsAtLeastO.java)
+java -cp /path/to/android.jar:/path/to/support-compat.jar:javac-9-dev-r3297-4.jar:error_prone_refaster-2.0.18.jar com.google.errorprone.refaster.RefasterRuleCompiler IsAtLeastO.java --out `pwd`/myrule.refaster
+
+2. Update build to use the refaster rule
+Add compiler args to error-prone in SupportLibraryPlugin.groovy
+'-XepPatchChecks:refaster:/path/to/refaster/myrule.refaster',
+'-XepPatchLocation:' + project.projectDir
+
+3. Compile support library using the refaster rule
+./gradlew assembleErrorProne
+
+4. Apply patches
+error-prone will produce patch files like "design/error-prone.patch" and to apply them, cd into the
+directory e.g. "design" and then run:
+patch -p0 -u -i error-prone.patch
+
+5. Rules have been applied! Celebrate!
\ No newline at end of file
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
index 98d6452..93ee3e0 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserCompat.java
@@ -24,7 +24,8 @@
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION;
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEARCH;
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
-import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
+import static android.support.v4.media.MediaBrowserProtocol
+        .CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_VERSION_CURRENT;
 import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
 import static android.support.v4.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
@@ -69,7 +70,6 @@
 import android.support.v4.media.session.IMediaSession;
 import android.support.v4.media.session.MediaControllerCompat.TransportControls;
 import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.os.ResultReceiver;
 import android.support.v4.util.ArrayMap;
 import android.text.TextUtils;
@@ -181,7 +181,7 @@
             ConnectionCallback callback, Bundle rootHints) {
         // To workaround an issue of {@link #unsubscribe(String, SubscriptionCallback)} on API 24
         // and 25 devices, use the support library version of implementation on those devices.
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             mImpl = new MediaBrowserImplApi24(context, serviceComponent, callback, rootHints);
         } else if (Build.VERSION.SDK_INT >= 23) {
             mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints);
@@ -676,7 +676,7 @@
         WeakReference<Subscription> mSubscriptionRef;
 
         public SubscriptionCallback() {
-            if (BuildCompat.isAtLeastO()) {
+            if (Build.VERSION.SDK_INT >= 26) {
                 mSubscriptionCallbackObj =
                         MediaBrowserCompatApi24.createSubscriptionCallback(new StubApi24());
                 mToken = null;
diff --git a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
index 12617b7..7c4c761 100644
--- a/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
+++ b/media-compat/java/android/support/v4/media/MediaBrowserServiceCompat.java
@@ -25,7 +25,8 @@
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION;
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEARCH;
 import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
-import static android.support.v4.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
+import static android.support.v4.media.MediaBrowserProtocol
+        .CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
 import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
 import static android.support.v4.media.MediaBrowserProtocol.DATA_CALLING_UID;
 import static android.support.v4.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
@@ -68,7 +69,6 @@
 import android.support.v4.app.BundleCompat;
 import android.support.v4.media.session.IMediaSession;
 import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.os.ResultReceiver;
 import android.support.v4.util.ArrayMap;
 import android.support.v4.util.Pair;
@@ -977,7 +977,7 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             mImpl = new MediaBrowserServiceImplApi24();
         } else if (Build.VERSION.SDK_INT >= 23) {
             mImpl = new MediaBrowserServiceImplApi23();
diff --git a/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java b/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
index afb72945..d411131 100644
--- a/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
+++ b/media-compat/java/android/support/v4/media/session/MediaButtonReceiver.java
@@ -24,11 +24,11 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Build;
 import android.os.RemoteException;
 import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.MediaBrowserServiceCompat;
 import android.support.v4.media.session.PlaybackStateCompat.MediaKeyAction;
-import android.support.v4.os.BuildCompat;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -284,7 +284,7 @@
     }
 
     private static void startForegroundService(Context context, Intent intent) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             context.startForegroundService(intent);
         } else {
             context.startService(intent);
diff --git a/samples/SupportTransitionDemos/res/layout/change_transform.xml b/samples/SupportTransitionDemos/res/layout/change_transform.xml
index 35909e3..c9559ab 100644
--- a/samples/SupportTransitionDemos/res/layout/change_transform.xml
+++ b/samples/SupportTransitionDemos/res/layout/change_transform.xml
@@ -32,6 +32,8 @@
         android:id="@+id/container_1"
         android:layout_width="match_parent"
         android:layout_height="0dp"
+        android:layout_marginEnd="128dp"
+        android:layout_marginRight="128dp"
         android:layout_weight="1"
         android:background="#BBDEFB"/>
 
@@ -39,6 +41,8 @@
         android:id="@+id/container_2"
         android:layout_width="match_parent"
         android:layout_height="0dp"
+        android:layout_marginLeft="128dp"
+        android:layout_marginStart="128dp"
         android:layout_weight="1"
         android:background="#FFCC80"/>
 
diff --git a/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
index 67aa409..af1bafd 100644
--- a/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
+++ b/samples/SupportTransitionDemos/src/com/example/android/support/transition/widget/ChangeTransformUsage.java
@@ -17,8 +17,10 @@
 package com.example.android.support.transition.widget;
 
 import android.os.Bundle;
+import android.support.transition.ArcMotion;
 import android.support.transition.ChangeTransform;
 import android.support.transition.TransitionManager;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -45,6 +47,8 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mChangeTransform = new ChangeTransform();
+        mChangeTransform.setInterpolator(new FastOutSlowInInterpolator());
+        mChangeTransform.setPathMotion(new ArcMotion());
         mRoot = findViewById(R.id.root);
         mContainer1 = findViewById(R.id.container_1);
         mContainer2 = findViewById(R.id.container_2);
diff --git a/samples/SupportWearDemos/AndroidManifest.xml b/samples/SupportWearDemos/AndroidManifest.xml
index df77ef7..eb10f0a 100644
--- a/samples/SupportWearDemos/AndroidManifest.xml
+++ b/samples/SupportWearDemos/AndroidManifest.xml
@@ -18,9 +18,12 @@
     package="com.example.android.support.wear" >
     <uses-feature android:name="android.hardware.type.watch" />
 
-    <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos" >
+    <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos"
+            android:theme="@android:style/Theme.DeviceDefault">
         <activity android:name="com.example.android.support.wear.app.SimpleWearableRecyclerViewDemo">
         </activity>
+        <activity android:name="com.example.android.support.wear.app.WearableSwitchDemo">
+        </activity>
         <activity android:name="com.example.android.support.wear.app.MainDemoActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/samples/SupportWearDemos/build.gradle b/samples/SupportWearDemos/build.gradle
index 2819768..0eac8a1 100644
--- a/samples/SupportWearDemos/build.gradle
+++ b/samples/SupportWearDemos/build.gradle
@@ -24,7 +24,7 @@
     compileSdkVersion project.ext.currentSdk
 
     defaultConfig {
-        minSdkVersion 23
+        minSdkVersion 24
         targetSdkVersion project.ext.currentSdk
     }
 
diff --git a/samples/SupportWearDemos/res/layout/switch_demo.xml b/samples/SupportWearDemos/res/layout/switch_demo.xml
new file mode 100644
index 0000000..921568c
--- /dev/null
+++ b/samples/SupportWearDemos/res/layout/switch_demo.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+    <Switch
+            style="@style/Widget.Wear.RoundSwitch"
+            android:layout_gravity="center"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"/>
+</merge>
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
index 26dbef7..c9512a2 100644
--- a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
@@ -50,9 +50,10 @@
 
     private Map<String, Intent> createContentMap() {
         Map<String, Intent> contentMap = new HashMap<>();
-        Intent intent = new Intent();
-        intent.setClass(MainDemoActivity.this, SimpleWearableRecyclerViewDemo.class);
-        contentMap.put("Wearable Recycler View", intent);
+        contentMap.put("Wearable Recycler View", new Intent(
+                this, SimpleWearableRecyclerViewDemo.class));
+        contentMap.put("Wearable Switch", new Intent(
+                this, WearableSwitchDemo.class));
 
         return contentMap;
     }
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
new file mode 100644
index 0000000..774021b
--- /dev/null
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.support.wear.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.example.android.support.wear.R;
+
+/** Main activity for the Switch demo. */
+public class WearableSwitchDemo extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.switch_demo);
+    }
+}
diff --git a/transition/api14/android/support/transition/GhostViewApi14.java b/transition/api14/android/support/transition/GhostViewApi14.java
index 9c91c99..c918651 100644
--- a/transition/api14/android/support/transition/GhostViewApi14.java
+++ b/transition/api14/android/support/transition/GhostViewApi14.java
@@ -150,6 +150,8 @@
         final int[] viewLocation = new int[2];
         getLocationOnScreen(location);
         mView.getLocationOnScreen(viewLocation);
+        viewLocation[0] -= mView.getTranslationX();
+        viewLocation[1] -= mView.getTranslationY();
         mDeltaX = viewLocation[0] - location[0];
         mDeltaY = viewLocation[1] - location[1];
         // Monitor invalidation of the target view.
diff --git a/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
index a51c4d6..a1038de 100644
--- a/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
+++ b/transition/api14/android/support/transition/ObjectAnimatorUtilsApi14.java
@@ -18,7 +18,6 @@
 
 import android.animation.ObjectAnimator;
 import android.graphics.Path;
-import android.graphics.PathMeasure;
 import android.graphics.PointF;
 import android.support.annotation.RequiresApi;
 import android.util.Property;
@@ -31,47 +30,4 @@
         return ObjectAnimator.ofFloat(target, new PathProperty<>(property, path), 0f, 1f);
     }
 
-    /**
-     * A special {@link Property} that can animate a pair of properties bi-dimensionally along the
-     * specified path.
-     * <p>
-     * This property should always be used with Animator that sets float fractions between
-     * {@code 0.f} and {@code 1.f}. For example, setting {@code 0.5f} to this property sets the
-     * values right in the middle of the specified path to the underlying properties.
-     * <p>
-     * Unlike many of the platform built-in properties, instances of this class cannot be reused
-     * for later animations.
-     */
-    private static class PathProperty<T> extends Property<T, Float> {
-
-        private final Property<T, PointF> mProperty;
-        private final PathMeasure mPathMeasure;
-        private final float mPathLength;
-        private final float[] mPosition = new float[2];
-        private final PointF mPointF = new PointF();
-        private float mCurrentFraction;
-
-        PathProperty(Property<T, PointF> property, Path path) {
-            super(Float.class, property.getName());
-            mProperty = property;
-            mPathMeasure = new PathMeasure(path, false);
-            mPathLength = mPathMeasure.getLength();
-        }
-
-        @Override
-        public Float get(T object) {
-            return mCurrentFraction;
-        }
-
-        @Override
-        public void set(T target, Float fraction) {
-            mCurrentFraction = fraction;
-            mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
-            mPointF.x = mPosition[0];
-            mPointF.y = mPosition[1];
-            mProperty.set(target, mPointF);
-        }
-
-    }
-
 }
diff --git a/transition/api14/android/support/transition/PathProperty.java b/transition/api14/android/support/transition/PathProperty.java
new file mode 100644
index 0000000..c5e7429
--- /dev/null
+++ b/transition/api14/android/support/transition/PathProperty.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.transition;
+
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PointF;
+import android.util.Property;
+
+/**
+ * A special {@link Property} that can animate a pair of properties bi-dimensionally along the
+ * specified path.
+ * <p>
+ * This property should always be used with Animator that sets float fractions between
+ * {@code 0.f} and {@code 1.f}. For example, setting {@code 0.5f} to this property sets the
+ * values right in the middle of the specified path to the underlying properties.
+ * <p>
+ * Unlike many of the platform built-in properties, instances of this class cannot be reused
+ * for later animations.
+ */
+class PathProperty<T> extends Property<T, Float> {
+
+    private final Property<T, PointF> mProperty;
+    private final PathMeasure mPathMeasure;
+    private final float mPathLength;
+    private final float[] mPosition = new float[2];
+    private final PointF mPointF = new PointF();
+    private float mCurrentFraction;
+
+    PathProperty(Property<T, PointF> property, Path path) {
+        super(Float.class, property.getName());
+        mProperty = property;
+        mPathMeasure = new PathMeasure(path, false);
+        mPathLength = mPathMeasure.getLength();
+    }
+
+    @Override
+    public Float get(T object) {
+        return mCurrentFraction;
+    }
+
+    @Override
+    public void set(T target, Float fraction) {
+        mCurrentFraction = fraction;
+        mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
+        mPointF.x = mPosition[0];
+        mPointF.y = mPosition[1];
+        mProperty.set(target, mPointF);
+    }
+
+}
diff --git a/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
index 7bcd36e..072178b 100644
--- a/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
+++ b/transition/api14/android/support/transition/PropertyValuesHolderUtilsApi14.java
@@ -17,9 +17,7 @@
 package android.support.transition;
 
 import android.animation.PropertyValuesHolder;
-import android.animation.TypeEvaluator;
 import android.graphics.Path;
-import android.graphics.PathMeasure;
 import android.graphics.PointF;
 import android.support.annotation.RequiresApi;
 import android.util.Property;
@@ -29,28 +27,7 @@
 
     @Override
     public PropertyValuesHolder ofPointF(Property<?, PointF> property, Path path) {
-        return PropertyValuesHolder.ofObject(property, new PathEvaluator(path));
-    }
-
-    private static class PathEvaluator implements TypeEvaluator<PointF> {
-
-        private final PointF mPointF = new PointF();
-        private final PathMeasure mPathMeasure;
-        private final float mPathLength;
-        private final float[] mPosition = new float[2];
-
-        PathEvaluator(Path path) {
-            mPathMeasure = new PathMeasure(path, false);
-            mPathLength = mPathMeasure.getLength();
-        }
-
-        @Override
-        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
-            mPathMeasure.getPosTan(mPathLength * fraction, mPosition, null);
-            mPointF.set(mPosition[0], mPosition[1]);
-            return mPointF;
-        }
-
+        return PropertyValuesHolder.ofFloat(new PathProperty<>(property, path), 0f, 1f);
     }
 
 }
diff --git a/transition/src/android/support/transition/ArcMotion.java b/transition/src/android/support/transition/ArcMotion.java
index a89ce4c..42f667c 100644
--- a/transition/src/android/support/transition/ArcMotion.java
+++ b/transition/src/android/support/transition/ArcMotion.java
@@ -37,6 +37,14 @@
  * {@link #setMinimumVerticalAngle(float)} may be used to set the minimum angle of the
  * arc between two points.
  * </p>
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>{@code
+ * <changeBounds>
+ *   <arcMotion android:minimumHorizontalAngle="15"
+ *              android:minimumVerticalAngle="0"
+ *              android:maximumAngle="90"/>
+ * </changeBounds>}
+ * </pre>
  */
 public class ArcMotion extends PathMotion {
 
diff --git a/transition/src/android/support/transition/ChangeTransform.java b/transition/src/android/support/transition/ChangeTransform.java
index 539a89e..f0adc08 100644
--- a/transition/src/android/support/transition/ChangeTransform.java
+++ b/transition/src/android/support/transition/ChangeTransform.java
@@ -19,10 +19,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
+import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.PointF;
 import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.v4.content.res.TypedArrayUtils;
@@ -59,16 +61,35 @@
             PROPNAME_PARENT_MATRIX,
     };
 
-    private static final Property<View, Matrix> ANIMATION_MATRIX_PROPERTY =
-            new Property<View, Matrix>(Matrix.class, "animationMatrix") {
+    /**
+     * This property sets the animation matrix properties that are not translations.
+     */
+    private static final Property<PathAnimatorMatrix, float[]> NON_TRANSLATIONS_PROPERTY =
+            new Property<PathAnimatorMatrix, float[]>(float[].class, "nonTranslations") {
                 @Override
-                public Matrix get(View view) {
+                public float[] get(PathAnimatorMatrix object) {
                     return null;
                 }
 
                 @Override
-                public void set(View view, Matrix matrix) {
-                    ViewUtils.setAnimationMatrix(view, matrix);
+                public void set(PathAnimatorMatrix object, float[] value) {
+                    object.setValues(value);
+                }
+            };
+
+    /**
+     * This property sets the translation animation matrix properties.
+     */
+    private static final Property<PathAnimatorMatrix, PointF> TRANSLATIONS_PROPERTY =
+            new Property<PathAnimatorMatrix, PointF>(PointF.class, "translations") {
+                @Override
+                public PointF get(PathAnimatorMatrix object) {
+                    return null;
+                }
+
+                @Override
+                public void set(PathAnimatorMatrix object, PointF value) {
+                    object.setTranslation(value);
                 }
             };
 
@@ -278,8 +299,23 @@
         final View view = endValues.view;
         setIdentityTransforms(view);
 
-        ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
-                new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
+        final float[] startMatrixValues = new float[9];
+        startMatrix.getValues(startMatrixValues);
+        final float[] endMatrixValues = new float[9];
+        endMatrix.getValues(endMatrixValues);
+        final PathAnimatorMatrix pathAnimatorMatrix =
+                new PathAnimatorMatrix(view, startMatrixValues);
+
+        PropertyValuesHolder valuesProperty = PropertyValuesHolder.ofObject(
+                NON_TRANSLATIONS_PROPERTY, new FloatArrayEvaluator(new float[9]),
+                startMatrixValues, endMatrixValues);
+        Path path = getPathMotion().getPath(startMatrixValues[Matrix.MTRANS_X],
+                startMatrixValues[Matrix.MTRANS_Y], endMatrixValues[Matrix.MTRANS_X],
+                endMatrixValues[Matrix.MTRANS_Y]);
+        PropertyValuesHolder translationProperty = PropertyValuesHolderUtils.ofPointF(
+                TRANSLATIONS_PROPERTY, path);
+        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(pathAnimatorMatrix,
+                valuesProperty, translationProperty);
 
         final Matrix finalEndMatrix = endMatrix;
 
@@ -302,14 +338,13 @@
                         view.setTag(R.id.parent_matrix, null);
                     }
                 }
-                ANIMATION_MATRIX_PROPERTY.set(view, null);
+                ViewUtils.setAnimationMatrix(view, null);
                 transforms.restore(view);
             }
 
             @Override
             public void onAnimationPause(Animator animation) {
-                ValueAnimator animator = (ValueAnimator) animation;
-                Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
+                Matrix currentMatrix = pathAnimatorMatrix.getMatrix();
                 setCurrentMatrix(currentMatrix);
             }
 
@@ -471,7 +506,7 @@
 
     }
 
-    private static class GhostListener extends Transition.TransitionListenerAdapter {
+    private static class GhostListener extends TransitionListenerAdapter {
 
         private View mView;
         private GhostViewImpl mGhostView;
@@ -501,4 +536,48 @@
 
     }
 
+    /**
+     * PathAnimatorMatrix allows the translations and the rest of the matrix to be set
+     * separately. This allows the PathMotion to affect the translations while scale
+     * and rotation are evaluated separately.
+     */
+    private static class PathAnimatorMatrix {
+
+        private final Matrix mMatrix = new Matrix();
+        private final View mView;
+        private final float[] mValues;
+        private float mTranslationX;
+        private float mTranslationY;
+
+        PathAnimatorMatrix(View view, float[] values) {
+            mView = view;
+            mValues = values.clone();
+            mTranslationX = mValues[Matrix.MTRANS_X];
+            mTranslationY = mValues[Matrix.MTRANS_Y];
+            setAnimationMatrix();
+        }
+
+        void setValues(float[] values) {
+            System.arraycopy(values, 0, mValues, 0, values.length);
+            setAnimationMatrix();
+        }
+
+        void setTranslation(PointF translation) {
+            mTranslationX = translation.x;
+            mTranslationY = translation.y;
+            setAnimationMatrix();
+        }
+
+        private void setAnimationMatrix() {
+            mValues[Matrix.MTRANS_X] = mTranslationX;
+            mValues[Matrix.MTRANS_Y] = mTranslationY;
+            mMatrix.setValues(mValues);
+            ViewUtils.setAnimationMatrix(mView, mMatrix);
+        }
+
+        Matrix getMatrix() {
+            return mMatrix;
+        }
+    }
+
 }
diff --git a/transition/src/android/support/transition/FloatArrayEvaluator.java b/transition/src/android/support/transition/FloatArrayEvaluator.java
new file mode 100644
index 0000000..81b97b7
--- /dev/null
+++ b/transition/src/android/support/transition/FloatArrayEvaluator.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.support.transition;
+
+import android.animation.TypeEvaluator;
+
+/**
+ * This evaluator can be used to perform type interpolation between <code>float[]</code> values.
+ * Each index into the array is treated as a separate value to interpolate. For example,
+ * evaluating <code>{100, 200}</code> and <code>{300, 400}</code> will interpolate the value at
+ * the first index between 100 and 300 and the value at the second index value between 200 and 400.
+ */
+class FloatArrayEvaluator implements TypeEvaluator<float[]> {
+
+    private float[] mArray;
+
+    /**
+     * Create a FloatArrayEvaluator that reuses <code>reuseArray</code> for every evaluate() call.
+     * Caution must be taken to ensure that the value returned from
+     * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or
+     * used across threads. The value will be modified on each <code>evaluate()</code> call.
+     *
+     * @param reuseArray The array to modify and return from <code>evaluate</code>.
+     */
+    FloatArrayEvaluator(float[] reuseArray) {
+        mArray = reuseArray;
+    }
+
+    /**
+     * Interpolates the value at each index by the fraction. If
+     * {@link #FloatArrayEvaluator(float[])} was used to construct this object,
+     * <code>reuseArray</code> will be returned, otherwise a new <code>float[]</code>
+     * will be returned.
+     *
+     * @param fraction   The fraction from the starting to the ending values
+     * @param startValue The start value.
+     * @param endValue   The end value.
+     * @return A <code>float[]</code> where each element is an interpolation between
+     * the same index in startValue and endValue.
+     */
+    @Override
+    public float[] evaluate(float fraction, float[] startValue, float[] endValue) {
+        float[] array = mArray;
+        if (array == null) {
+            array = new float[startValue.length];
+        }
+
+        for (int i = 0; i < array.length; i++) {
+            float start = startValue[i];
+            float end = endValue[i];
+            array[i] = start + (fraction * (end - start));
+        }
+        return array;
+    }
+
+}
diff --git a/transition/src/android/support/transition/PathMotion.java b/transition/src/android/support/transition/PathMotion.java
index 513b61e..d270a08 100644
--- a/transition/src/android/support/transition/PathMotion.java
+++ b/transition/src/android/support/transition/PathMotion.java
@@ -29,6 +29,14 @@
  * have these motions move in a curve can change how Views interpolate in two dimensions
  * by extending PathMotion and implementing {@link #getPath(float, float, float, float)}.
  * </p>
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ *     <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>
+ * }
+ * </pre>
  */
 public abstract class PathMotion {
 
diff --git a/transition/src/android/support/transition/PatternPathMotion.java b/transition/src/android/support/transition/PatternPathMotion.java
index a8c6078..2ac6e72 100644
--- a/transition/src/android/support/transition/PatternPathMotion.java
+++ b/transition/src/android/support/transition/PatternPathMotion.java
@@ -31,6 +31,12 @@
  * A PathMotion that takes a Path pattern and applies it to the separation between two points.
  * The starting point of the Path will be moved to the origin and the end point will be scaled
  * and rotated so that it matches with the target end point.
+ * <p>This may be used in XML as an element inside a transition.</p>
+ * <pre>{@code
+ * <changeBounds>
+ *     <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * </changeBounds>}
+ * </pre>
  */
 public class PatternPathMotion extends PathMotion {
 
diff --git a/transition/src/android/support/transition/Transition.java b/transition/src/android/support/transition/Transition.java
index a2b38bc..04cc57b 100644
--- a/transition/src/android/support/transition/Transition.java
+++ b/transition/src/android/support/transition/Transition.java
@@ -2087,7 +2087,7 @@
      * @see PatternPathMotion
      * @see android.transition.PathMotion
      */
-    @Nullable
+    @NonNull
     public PathMotion getPathMotion() {
         return mPathMotion;
     }
@@ -2335,36 +2335,6 @@
     }
 
     /**
-     * Utility adapter class to avoid having to override all three methods
-     * whenever someone just wants to listen for a single event.
-     *
-     * @hide
-     */
-    @RestrictTo(LIBRARY_GROUP)
-    public static class TransitionListenerAdapter implements TransitionListener {
-
-        @Override
-        public void onTransitionStart(@NonNull Transition transition) {
-        }
-
-        @Override
-        public void onTransitionEnd(@NonNull Transition transition) {
-        }
-
-        @Override
-        public void onTransitionCancel(@NonNull Transition transition) {
-        }
-
-        @Override
-        public void onTransitionPause(@NonNull Transition transition) {
-        }
-
-        @Override
-        public void onTransitionResume(@NonNull Transition transition) {
-        }
-    }
-
-    /**
      * Holds information about each animator used when a new transition starts
      * while other transitions are still running to determine whether a running
      * animation should be canceled or a new animation noop'd. The structure holds
diff --git a/transition/src/android/support/transition/TransitionListenerAdapter.java b/transition/src/android/support/transition/TransitionListenerAdapter.java
new file mode 100644
index 0000000..333fbfb
--- /dev/null
+++ b/transition/src/android/support/transition/TransitionListenerAdapter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.transition;
+
+import android.support.annotation.NonNull;
+
+/**
+ * This adapter class provides empty implementations of the methods from {@link
+ * Transition.TransitionListener}.
+ * Any custom listener that cares only about a subset of the methods of this listener can
+ * simply subclass this adapter class instead of implementing the interface directly.
+ */
+public class TransitionListenerAdapter implements Transition.TransitionListener {
+
+    @Override
+    public void onTransitionStart(@NonNull Transition transition) {
+    }
+
+    @Override
+    public void onTransitionEnd(@NonNull Transition transition) {
+    }
+
+    @Override
+    public void onTransitionCancel(@NonNull Transition transition) {
+    }
+
+    @Override
+    public void onTransitionPause(@NonNull Transition transition) {
+    }
+
+    @Override
+    public void onTransitionResume(@NonNull Transition transition) {
+    }
+
+}
diff --git a/transition/src/android/support/transition/TransitionManager.java b/transition/src/android/support/transition/TransitionManager.java
index f65a464..d5f46ab 100644
--- a/transition/src/android/support/transition/TransitionManager.java
+++ b/transition/src/android/support/transition/TransitionManager.java
@@ -273,7 +273,7 @@
                 previousRunningTransitions = new ArrayList<>(currentTransitions);
             }
             currentTransitions.add(mTransition);
-            mTransition.addListener(new Transition.TransitionListenerAdapter() {
+            mTransition.addListener(new TransitionListenerAdapter() {
                 @Override
                 public void onTransitionEnd(@NonNull Transition transition) {
                     ArrayList<Transition> currentTransitions = runningTransitions.get(mSceneRoot);
diff --git a/transition/src/android/support/transition/ViewUtils.java b/transition/src/android/support/transition/ViewUtils.java
index bf671d0..66c3076 100644
--- a/transition/src/android/support/transition/ViewUtils.java
+++ b/transition/src/android/support/transition/ViewUtils.java
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v4.view.ViewCompat;
 import android.util.Log;
 import android.util.Property;
@@ -188,7 +189,7 @@
      * @param v The view
      * @param m The matrix
      */
-    static void setAnimationMatrix(@NonNull View v, @NonNull Matrix m) {
+    static void setAnimationMatrix(@NonNull View v, @Nullable Matrix m) {
         IMPL.setAnimationMatrix(v, m);
     }
 
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
index 65d2c44..262a5a6 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
@@ -37,7 +37,6 @@
 import android.support.v17.leanback.widget.BackgroundHelper;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.graphics.drawable.DrawableCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.animation.FastOutLinearInInterpolator;
 import android.util.Log;
 import android.view.View;
@@ -674,7 +673,7 @@
         // Activity transition below O has ghost effect for null window background where we
         // need set a transparent background to force redraw the whole window.
         mContext.getWindow().getDecorView().setBackground(
-                BuildCompat.isAtLeastO() ? null : new ColorDrawable(Color.TRANSPARENT));
+                Build.VERSION.SDK_INT >= 26 ? null : new ColorDrawable(Color.TRANSPARENT));
     }
 
     void attachToViewInternal(View sceneRoot) {
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
index 78136e2..c8d7b0a 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
@@ -31,7 +31,6 @@
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.NavUtils;
 import android.support.v4.app.TaskStackBuilder;
-import android.support.v4.os.BuildCompat;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.support.v7.widget.VectorEnabledTintResources;
@@ -549,7 +548,7 @@
      * and perform the corresponding action.
      */
     private boolean performMenuItemShortcut(int keycode, KeyEvent event) {
-        if (!BuildCompat.isAtLeastO() && !event.isCtrlPressed()
+        if (!(Build.VERSION.SDK_INT >= 26) && !event.isCtrlPressed()
                 && !KeyEvent.metaStateHasNoModifiers(event.getMetaState())
                 && event.getRepeatCount() == 0
                 && !KeyEvent.isModifierKey(event.getKeyCode())) {
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
index e79a906..2a4022c 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
@@ -26,11 +26,11 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
 import android.support.v7.view.SupportActionModeWrapper;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -217,7 +217,7 @@
                 res.updateConfiguration(config, metrics);
 
                 // We may need to flush the Resources' drawable cache due to framework bugs.
-                if (!BuildCompat.isAtLeastO()) {
+                if (!(Build.VERSION.SDK_INT >= 26)) {
                     ResourcesFlusher.flush(res);
                 }
             }
diff --git a/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java b/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
index fda1a97..73499cf 100644
--- a/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
+++ b/v7/appcompat/src/android/support/v7/view/menu/CascadingMenuPopup.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -28,7 +29,6 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.StyleRes;
 import android.support.v4.internal.view.SupportMenu;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.appcompat.R;
@@ -406,7 +406,7 @@
 
             final int parentOffsetLeft;
             final int parentOffsetTop;
-            if (BuildCompat.isAtLeastO()) {
+            if (Build.VERSION.SDK_INT >= 26) {
                 // Anchor the submenu directly to the parent menu item view. This allows for
                 // accurate submenu positioning when the parent menu is being moved.
                 popupWindow.setAnchorView(parentView);
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
index c5f6e17..def3f79 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
@@ -27,7 +27,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.widget.TextViewCompat;
 import android.support.v7.appcompat.R;
 import android.text.method.PasswordTransformationMethod;
@@ -171,7 +170,7 @@
 
         mAutoSizeTextHelper.loadFromAttributes(attrs, defStyleAttr);
 
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             // Delegate auto-size functionality to the framework implementation.
             if (mAutoSizeTextHelper.getAutoSizeTextType()
                     != TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE) {
@@ -283,7 +282,7 @@
     @RestrictTo(LIBRARY_GROUP)
     void onLayout(boolean changed, int left, int top, int right, int bottom) {
         // Auto-size is supported by the framework starting from Android O.
-        if (!BuildCompat.isAtLeastO()) {
+        if (!(Build.VERSION.SDK_INT >= 26)) {
             if (isAutoSizeEnabled()) {
                 if (getNeedsAutoSizeText()) {
                     // Call auto-size after the width and height have been calculated.
@@ -299,7 +298,7 @@
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     void setTextSize(int unit, float size) {
-        if (!BuildCompat.isAtLeastO()) {
+        if (!(Build.VERSION.SDK_INT >= 26)) {
             if (!isAutoSizeEnabled()) {
                 setTextSizeInternal(unit, size);
             }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
index 992ddc6..1ac0e8a 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
@@ -22,11 +22,11 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v4.widget.AutoSizeableTextView;
 import android.support.v4.widget.TextViewCompat;
@@ -183,7 +183,7 @@
 
     @Override
     public void setTextSize(int unit, float size) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             super.setTextSize(unit, size);
         } else {
             if (mTextHelper != null) {
@@ -203,7 +203,7 @@
     @Override
     public void setAutoSizeTextTypeWithDefaults(
             @TextViewCompat.AutoSizeTextType int autoSizeTextType) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             super.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
         } else {
             if (mTextHelper != null) {
@@ -226,7 +226,7 @@
             int autoSizeMaxTextSize,
             int autoSizeStepGranularity,
             int unit) throws IllegalArgumentException {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             super.setAutoSizeTextTypeUniformWithConfiguration(
                     autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
         } else {
@@ -248,7 +248,7 @@
     @Override
     public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
             throws IllegalArgumentException {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             super.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
         } else {
             if (mTextHelper != null) {
@@ -267,7 +267,7 @@
     @Override
     @TextViewCompat.AutoSizeTextType
     public int getAutoSizeTextType() {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return super.getAutoSizeTextType() == TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     ? TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     : TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
@@ -288,7 +288,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeStepGranularity() {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return super.getAutoSizeStepGranularity();
         } else {
             if (mTextHelper != null) {
@@ -307,7 +307,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMinTextSize() {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return super.getAutoSizeMinTextSize();
         } else {
             if (mTextHelper != null) {
@@ -326,7 +326,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMaxTextSize() {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return super.getAutoSizeMaxTextSize();
         } else {
             if (mTextHelper != null) {
@@ -345,7 +345,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int[] getAutoSizeTextAvailableSizes() {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return super.getAutoSizeTextAvailableSizes();
         } else {
             if (mTextHelper != null) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
index 068366a..9c83f9a 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextViewAutoSizeHelper.java
@@ -26,7 +26,6 @@
 import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.widget.TextViewCompat;
 import android.support.v7.appcompat.R;
 import android.text.Layout;
@@ -525,7 +524,7 @@
             // from {@link #loadFromAttributes}, in which case the auto-size configuration
             // attributes set up in this function will be read by {@link AppCompatTextHelper}
             // and after passed on to the actual TextView which will take care of auto-sizing.
-            if (!BuildCompat.isAtLeastO()) {
+            if (!(Build.VERSION.SDK_INT >= 26)) {
                 autoSizeText();
             }
         }
diff --git a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
index 6abdb75..bb400f1 100644
--- a/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/LinearLayoutCompat.java
@@ -1054,8 +1054,7 @@
 
             final int margin = lp.topMargin + lp.bottomMargin;
             final int childHeight = child.getMeasuredHeight() + margin;
-            childState = ViewUtils.combineMeasuredStates(childState,
-                    child.getMeasuredState());
+            childState = View.combineMeasuredStates(childState, child.getMeasuredState());
 
             if (baselineAligned) {
                 final int childBaseline = child.getBaseline();
diff --git a/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java b/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
index 24dafb3..d6f0099 100644
--- a/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
+++ b/v7/appcompat/src/android/support/v7/widget/SuggestionsAdapter.java
@@ -503,7 +503,7 @@
      * @return a Drawable, or null if none found
      */
     private Drawable getDrawableFromResourceValue(String drawableId) {
-        if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
+        if (drawableId == null || drawableId.isEmpty() || "0".equals(drawableId)) {
             return null;
         }
         try {
diff --git a/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java b/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
index b920505..0a86600 100644
--- a/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
+++ b/v7/appcompat/src/android/support/v7/widget/TintTypedArray.java
@@ -31,7 +31,6 @@
 import android.support.annotation.RestrictTo;
 import android.support.annotation.StyleableRes;
 import android.support.v4.content.res.ResourcesCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.util.TypedValue;
@@ -110,7 +109,7 @@
      */
     @Nullable
     public Typeface getFont(@StyleableRes int index, int style, @NonNull TextView targetView) {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             return mWrapped.getFont(index);
         }
         final int resourceId = mWrapped.getResourceId(index, 0);
diff --git a/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java b/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
index f7466bc..470c3b2 100644
--- a/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
+++ b/v7/appcompat/src/android/support/v7/widget/TooltipCompat.java
@@ -17,9 +17,9 @@
 package android.support.v7.widget;
 
 import android.annotation.TargetApi;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.v4.os.BuildCompat;
 import android.view.View;
 
 /**
@@ -49,7 +49,7 @@
 
     private static final ViewCompatImpl IMPL;
     static {
-        if (BuildCompat.isAtLeastO()) {
+        if (Build.VERSION.SDK_INT >= 26) {
             IMPL = new Api26ViewCompatImpl();
         } else {
             IMPL = new BaseViewCompatImpl();
diff --git a/v7/appcompat/src/android/support/v7/widget/ViewUtils.java b/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
index 58acb03..0f910c3 100644
--- a/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
+++ b/v7/appcompat/src/android/support/v7/widget/ViewUtils.java
@@ -58,21 +58,6 @@
     }
 
     /**
-     * Merge two states as returned by {@link View#getMeasuredState()} ()}.
-     * @param curState The current state as returned from a view or the result
-     * of combining multiple views.
-     * @param newState The new view state to combine.
-     * @return Returns a new integer reflecting the combination of the two
-     * states.
-     *
-     * @deprecated Use {@link View#combineMeasuredStates(int, int)} directly.
-     */
-    @Deprecated
-    public static int combineMeasuredStates(int curState, int newState) {
-        return View.combineMeasuredStates(curState, newState);
-    }
-
-    /**
      * Allow calling the hidden method {@code computeFitSystemWindows(Rect, Rect)} through
      * reflection on {@code view}.
      */
diff --git a/v7/cardview/src/android/support/v7/widget/CardView.java b/v7/cardview/src/android/support/v7/widget/CardView.java
index fab9453..3df45d9 100644
--- a/v7/cardview/src/android/support/v7/widget/CardView.java
+++ b/v7/cardview/src/android/support/v7/widget/CardView.java
@@ -196,6 +196,9 @@
                     widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minWidth,
                             MeasureSpec.getSize(widthMeasureSpec)), widthMode);
                     break;
+                case MeasureSpec.UNSPECIFIED:
+                    // Do nothing
+                    break;
             }
 
             final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
@@ -206,6 +209,9 @@
                     heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minHeight,
                             MeasureSpec.getSize(heightMeasureSpec)), heightMode);
                     break;
+                case MeasureSpec.UNSPECIFIED:
+                    // Do nothing
+                    break;
             }
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         } else {
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index a7e8cb5..00d15c9 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -489,7 +489,8 @@
             setEnabled(mRouter.isRouteAvailable(mSelector,
                     MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE));
         }
-        if (mRemoteIndicator.getCurrent() instanceof AnimationDrawable) {
+        if (mRemoteIndicator != null
+                && mRemoteIndicator.getCurrent() instanceof AnimationDrawable) {
             AnimationDrawable curDrawable = (AnimationDrawable) mRemoteIndicator.getCurrent();
             if (mAttachedToWindow) {
                 if ((needsRefresh || isConnecting) && !curDrawable.isRunning()) {
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index e01cd83..e452009 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -677,7 +677,7 @@
             int defStyleAttr, int defStyleRes) {
         if (className != null) {
             className = className.trim();
-            if (className.length() != 0) {  // Can't use isEmpty since it was added in API 9.
+            if (!className.isEmpty()) {
                 className = getFullClassName(context, className);
                 try {
                     ClassLoader classLoader;
diff --git a/wear/AndroidManifest.xml b/wear/AndroidManifest.xml
index fda54e2..5fa5a83 100644
--- a/wear/AndroidManifest.xml
+++ b/wear/AndroidManifest.xml
@@ -15,7 +15,6 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.support.wear">
-    <uses-sdk android:minSdkVersion="22"/>
     <application>
         <meta-data android:name="android.support.VERSION" android:value="${support-version}" />
     </application>
diff --git a/wear/build.gradle b/wear/build.gradle
index b320ab7..07e579e 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -19,7 +19,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion 23
+        minSdkVersion 24
     }
 
     sourceSets {
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res-public/values/public_styles.xml
similarity index 64%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res-public/values/public_styles.xml
index a2be3e1..d4575e4 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res-public/values/public_styles.xml
@@ -13,11 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/wearable_support_action_drawer_title"
-    android:layout_width="wrap_content"
-    android:layout_height="@dimen/action_drawer_item_icon_size"
-    android:layout_gravity="center"
-    android:gravity="center"
-    style="@style/WearableActionDrawerTitleText" />
+<!-- Definitions of styles to be exposed as public -->
+<resources>
+    <public type="style" name="Widget.Wear.RoundSwitch"/>
+</resources>
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/color/ws_switch_thumb_color_material.xml
similarity index 63%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res/color/ws_switch_thumb_color_material.xml
index a2be3e1..0707d69 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/color/ws_switch_thumb_color_material.xml
@@ -13,11 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/wearable_support_action_drawer_title"
-    android:layout_width="wrap_content"
-    android:layout_height="@dimen/action_drawer_item_icon_size"
-    android:layout_gravity="center"
-    android:gravity="center"
-    style="@style/WearableActionDrawerTitleText" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorButtonNormal"
+            android:alpha="?android:attr/disabledAlpha" android:state_enabled="false" />
+    <item android:color="?android:attr/colorControlActivated" android:state_checked="true" />
+    <item android:color="?android:attr/colorButtonNormal" />
+</selector>
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/color/ws_switch_track_color_material.xml
similarity index 65%
copy from wear/res/layout-v23/action_drawer_title_view.xml
copy to wear/res/color/ws_switch_track_color_material.xml
index a2be3e1..214bf4a 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/color/ws_switch_track_color_material.xml
@@ -13,11 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/wearable_support_action_drawer_title"
-    android:layout_width="wrap_content"
-    android:layout_height="@dimen/action_drawer_item_icon_size"
-    android:layout_gravity="center"
-    android:gravity="center"
-    style="@style/WearableActionDrawerTitleText" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorPrimary" />
+    <item android:color="?android:attr/colorPrimary" />
+</selector>
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..371469c
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..e477260
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..19a1bd3
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..79dc733
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..6d921c0
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/ws_switch_track_mtrl.png b/wear/res/drawable-hdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..ecee3e1
--- /dev/null
+++ b/wear/res/drawable-hdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-v21/ic_expand_more_white_22.xml b/wear/res/drawable-v21/ws_ic_expand_more_white_22.xml
similarity index 100%
rename from wear/res/drawable-v21/ic_expand_more_white_22.xml
rename to wear/res/drawable-v21/ws_ic_expand_more_white_22.xml
diff --git a/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml b/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml
new file mode 100644
index 0000000..15423e5
--- /dev/null
+++ b/wear/res/drawable-v21/ws_switch_thumb_material_anim.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:constantSize="true">
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+        android:state_enabled="false" />
+    <item
+        android:id="@+id/on"
+        android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+        android:state_checked="true" />
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/ws_switch_thumb_mtrl_14w" />
+    <transition
+        android:fromId="@id/off"
+        android:toId="@id/on">
+        <animation-list>
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
+    <transition
+        android:fromId="@id/on"
+        android:toId="@id/off">
+        <animation-list>
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/ws_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
+</animated-selector>
diff --git a/wear/res/drawable-v23/action_item_background.xml b/wear/res/drawable-v23/ws_action_item_background.xml
similarity index 100%
rename from wear/res/drawable-v23/action_item_background.xml
rename to wear/res/drawable-v23/ws_action_item_background.xml
diff --git a/wear/res/drawable-v23/action_item_icon_background.xml b/wear/res/drawable-v23/ws_action_item_icon_background.xml
similarity index 100%
rename from wear/res/drawable-v23/action_item_icon_background.xml
rename to wear/res/drawable-v23/ws_action_item_icon_background.xml
diff --git a/wear/res/drawable-v23/ic_expand_less_white_22.xml b/wear/res/drawable-v23/ws_ic_expand_less_white_22.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_expand_less_white_22.xml
rename to wear/res/drawable-v23/ws_ic_expand_less_white_22.xml
diff --git a/wear/res/drawable-v23/ic_more_horiz_24dp_wht.xml b/wear/res/drawable-v23/ws_ic_more_horiz_24dp_wht.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_more_horiz_24dp_wht.xml
rename to wear/res/drawable-v23/ws_ic_more_horiz_24dp_wht.xml
diff --git a/wear/res/drawable-v23/ic_more_vert_24dp_wht.xml b/wear/res/drawable-v23/ws_ic_more_vert_24dp_wht.xml
similarity index 100%
rename from wear/res/drawable-v23/ic_more_vert_24dp_wht.xml
rename to wear/res/drawable-v23/ws_ic_more_vert_24dp_wht.xml
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..7f7ca14
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..52120b8
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..d6e9be9
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..8d76393
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..ca9c66e
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png b/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..1aa5442
--- /dev/null
+++ b/wear/res/drawable-xhdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..c0d72d7
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..d7c0ec0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..5815ba9
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..41da8c0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..975eb01
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png b/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png
new file mode 100644
index 0000000..af2042b
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/ws_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/layout-v23/action_drawer_item_view.xml b/wear/res/layout-v23/ws_action_drawer_item_view.xml
similarity index 70%
rename from wear/res/layout-v23/action_drawer_item_view.xml
rename to wear/res/layout-v23/ws_action_drawer_item_view.xml
index 068e364..fc84862 100644
--- a/wear/res/layout-v23/action_drawer_item_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_item_view.xml
@@ -18,24 +18,24 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="@drawable/action_item_background"
+    android:background="@drawable/ws_action_item_background"
     android:orientation="horizontal">
 
     <ImageView
-        android:id="@+id/wearable_support_action_drawer_item_icon"
-        android:layout_width="@dimen/action_drawer_item_icon_size"
-        android:layout_height="@dimen/action_drawer_item_icon_size"
+        android:id="@+id/ws_action_drawer_item_icon"
+        android:layout_width="@dimen/ws_action_drawer_item_icon_size"
+        android:layout_height="@dimen/ws_action_drawer_item_icon_size"
         android:layout_gravity="center_vertical"
-        android:background="@drawable/action_item_icon_background"
+        android:background="@drawable/ws_action_item_icon_background"
         android:tint="?android:attr/colorBackground"
-        android:padding="@dimen/action_drawer_item_icon_padding"
+        android:padding="@dimen/ws_action_drawer_item_icon_padding"
         android:scaleType="fitCenter"
         tools:ignore="ContentDescription" />
 
     <TextView
-        android:id="@+id/wearable_support_action_drawer_item_text"
+        android:id="@+id/ws_action_drawer_item_text"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        style="@style/WearableActionDrawerItemText"/>
+        style="@style/WsWearableActionDrawerItemText"/>
 
 </LinearLayout>
diff --git a/wear/res/layout-v23/action_drawer_peek_view.xml b/wear/res/layout-v23/ws_action_drawer_peek_view.xml
similarity index 66%
rename from wear/res/layout-v23/action_drawer_peek_view.xml
rename to wear/res/layout-v23/ws_action_drawer_peek_view.xml
index 88946cb..ce66d73 100644
--- a/wear/res/layout-v23/action_drawer_peek_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_peek_view.xml
@@ -17,25 +17,25 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/action_drawer_peek_view_height"
+    android:layout_height="@dimen/ws_action_drawer_peek_view_height"
     android:layout_gravity="center"
     android:gravity="center_vertical"
     android:orientation="vertical"
-    android:paddingTop="@dimen/action_drawer_peek_top_padding">
+    android:paddingTop="@dimen/ws_action_drawer_peek_top_padding">
 
     <ImageView
-        android:id="@+id/wearable_support_action_drawer_peek_action_icon"
-        android:layout_width="@dimen/peek_view_icon_size"
-        android:layout_height="@dimen/peek_view_icon_size"
+        android:id="@+id/ws_action_drawer_peek_action_icon"
+        android:layout_width="@dimen/ws_peek_view_icon_size"
+        android:layout_height="@dimen/ws_peek_view_icon_size"
         android:tint="?android:attr/colorForeground"
         tools:ignore="ContentDescription" />
 
     <ImageView
-        android:id="@+id/wearable_support_action_drawer_expand_icon"
-        android:layout_width="@dimen/peek_view_icon_size"
-        android:layout_height="@dimen/peek_view_icon_size"
-        android:layout_marginTop="@dimen/action_drawer_expand_icon_top_margin"
-        android:src="@drawable/ic_expand_less_white_22"
+        android:id="@+id/ws_action_drawer_expand_icon"
+        android:layout_width="@dimen/ws_peek_view_icon_size"
+        android:layout_height="@dimen/ws_peek_view_icon_size"
+        android:layout_marginTop="@dimen/ws_action_drawer_expand_icon_top_margin"
+        android:src="@drawable/ws_ic_expand_less_white_22"
         android:alpha="0.5"
         android:tint="?android:attr/colorForeground"
         tools:ignore="NegativeMargin,ContentDescription" />
diff --git a/wear/res/layout-v23/action_drawer_title_view.xml b/wear/res/layout-v23/ws_action_drawer_title_view.xml
similarity index 83%
rename from wear/res/layout-v23/action_drawer_title_view.xml
rename to wear/res/layout-v23/ws_action_drawer_title_view.xml
index a2be3e1..e5535c4 100644
--- a/wear/res/layout-v23/action_drawer_title_view.xml
+++ b/wear/res/layout-v23/ws_action_drawer_title_view.xml
@@ -15,9 +15,9 @@
 -->
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/wearable_support_action_drawer_title"
+    android:id="@+id/ws_action_drawer_title"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/action_drawer_item_icon_size"
+    android:layout_height="@dimen/ws_action_drawer_item_icon_size"
     android:layout_gravity="center"
     android:gravity="center"
-    style="@style/WearableActionDrawerTitleText" />
+    style="@style/WsWearableActionDrawerTitleText" />
diff --git a/wear/res/layout-v23/wearable_drawer_view.xml b/wear/res/layout-v23/ws_wearable_drawer_view.xml
similarity index 74%
rename from wear/res/layout-v23/wearable_drawer_view.xml
rename to wear/res/layout-v23/ws_wearable_drawer_view.xml
index 8659aac..c7c5907 100644
--- a/wear/res/layout-v23/wearable_drawer_view.xml
+++ b/wear/res/layout-v23/ws_wearable_drawer_view.xml
@@ -19,16 +19,16 @@
 
     <!-- Layout gravity for peek is set in code by WearableDrawerView. -->
     <FrameLayout
-        android:id="@+id/wearable_support_drawer_view_peek_container"
+        android:id="@+id/ws_drawer_view_peek_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
         <ImageView
-            android:id="@+id/wearable_support_drawer_view_peek_icon"
-            android:layout_width="@dimen/peek_view_icon_size"
-            android:layout_height="@dimen/peek_view_icon_size"
-            android:layout_marginTop="@dimen/peek_view_top_padding"
-            android:layout_marginBottom="@dimen/peek_view_bottom_padding"
+            android:id="@+id/ws_drawer_view_peek_icon"
+            android:layout_width="@dimen/ws_peek_view_icon_size"
+            android:layout_height="@dimen/ws_peek_view_icon_size"
+            android:layout_marginTop="@dimen/ws_peek_view_top_padding"
+            android:layout_marginBottom="@dimen/ws_peek_view_bottom_padding"
             android:layout_gravity="center"
             android:tint="?android:attr/colorForeground"
             tools:ignore="ContentDescription" />
diff --git a/wear/res/layout/single_page_nav_drawer_5_item.xml b/wear/res/layout/single_page_nav_drawer_5_item.xml
deleted file mode 100644
index 2a8c3af..0000000
--- a/wear/res/layout/single_page_nav_drawer_5_item.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false">
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_5_items_horizontal_outer_rows"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_5_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle"/>
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
-        android:layout_alignParentEnd="true"
-        android:layout_alignParentTop="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_5_items_horizontal_outer_rows"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_5_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_2"
-        android:layout_alignParentStart="true"
-        android:layout_centerVertical="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_5_items_horizontal_middle_row"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_3"
-        android:layout_centerInParent="true"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_4"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_5_items_horizontal_middle_row"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <TextView
-        android:id="@+id/wearable_support_nav_drawer_text"
-        android:layout_below="@id/wearable_support_nav_drawer_icon_4"
-        style="@style/SinglePageNavDrawerTextStyle"/>
-
-</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_7_item.xml b/wear/res/layout/single_page_nav_drawer_7_item.xml
deleted file mode 100644
index 45e0c24..0000000
--- a/wear/res/layout/single_page_nav_drawer_7_item.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false">
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_7_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
-        android:layout_alignParentEnd="true"
-        android:layout_alignParentTop="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_7_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_2"
-        android:layout_alignParentStart="true"
-        android:layout_centerVertical="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_middle_row"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_3"
-        android:layout_centerInParent="true"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_4"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_middle_row"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_5"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentBottom="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
-        app:layout_marginBottomPercent="@fraction/nav_drawer_margin_7_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-    <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_6"
-        android:layout_alignParentEnd="true"
-        android:layout_alignParentBottom="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_7_items_horizontal_outer_rows"
-        app:layout_marginBottomPercent="@fraction/nav_drawer_margin_7_items_vertical"
-        tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
-
-</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/navigation_drawer_item_view.xml b/wear/res/layout/ws_navigation_drawer_item_view.xml
similarity index 86%
rename from wear/res/layout/navigation_drawer_item_view.xml
rename to wear/res/layout/ws_navigation_drawer_item_view.xml
index 9e4d86a..dcd5e41 100644
--- a/wear/res/layout/navigation_drawer_item_view.xml
+++ b/wear/res/layout/ws_navigation_drawer_item_view.xml
@@ -19,17 +19,17 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
     <ImageView
-        android:id="@+id/wearable_support_navigation_drawer_item_icon"
+        android:id="@+id/ws_navigation_drawer_item_icon"
         android:layout_width="48dp"
         android:layout_height="48dp"
         android:layout_centerInParent="true"
         android:scaleType="fitCenter"
         tools:ignore="ContentDescription" />
     <TextView
-        android:id="@+id/wearable_support_navigation_drawer_item_text"
+        android:id="@+id/ws_navigation_drawer_item_text"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_below="@id/wearable_support_navigation_drawer_item_icon"
+        android:layout_below="@id/ws_navigation_drawer_item_icon"
         android:layout_marginTop="6dp"
         android:gravity="center_horizontal"
         android:textColor="?android:attr/textColorPrimary"/>
diff --git a/wear/res/layout/navigation_drawer_view.xml b/wear/res/layout/ws_navigation_drawer_view.xml
similarity index 78%
rename from wear/res/layout/navigation_drawer_view.xml
rename to wear/res/layout/ws_navigation_drawer_view.xml
index 9824bbf..92855eb 100644
--- a/wear/res/layout/navigation_drawer_view.xml
+++ b/wear/res/layout/ws_navigation_drawer_view.xml
@@ -20,15 +20,15 @@
     android:layout_height="match_parent" >
 
     <android.support.v4.view.ViewPager
-        android:id="@+id/wearable_support_navigation_drawer_view_pager"
+        android:id="@+id/ws_navigation_drawer_view_pager"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
     <android.support.wear.widget.drawer.PageIndicatorView
-        android:id="@+id/wearable_support_navigation_drawer_page_indicator"
+        android:id="@+id/ws_navigation_drawer_page_indicator"
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/peek_view_icon_size"
-        android:layout_marginBottom="@dimen/peek_view_bottom_padding"
+        android:layout_height="@dimen/ws_peek_view_icon_size"
+        android:layout_marginBottom="@dimen/ws_peek_view_bottom_padding"
         android:layout_gravity="bottom|center_horizontal"
-        app:pageIndicatorDotFadeWhenIdle="false" />
+        app:dotFadeWhenIdle="false" />
 
 </FrameLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_1_item.xml b/wear/res/layout/ws_single_page_nav_drawer_1_item.xml
similarity index 79%
rename from wear/res/layout/single_page_nav_drawer_1_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_1_item.xml
index 2911f43..550d737 100644
--- a/wear/res/layout/single_page_nav_drawer_1_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_1_item.xml
@@ -20,14 +20,14 @@
     android:clipChildren="false">
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
+        android:id="@+id/ws_nav_drawer_icon_0"
         android:layout_centerInParent="true"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <TextView
-        android:id="@+id/wearable_support_nav_drawer_text"
-        android:layout_below="@id/wearable_support_nav_drawer_icon_0"
-        style="@style/SinglePageNavDrawerTextStyle"/>
+        android:id="@+id/ws_nav_drawer_text"
+        android:layout_below="@id/ws_nav_drawer_icon_0"
+        style="@style/WsSinglePageNavDrawerTextStyle"/>
 
 </android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_2_item.xml b/wear/res/layout/ws_single_page_nav_drawer_2_item.xml
similarity index 71%
rename from wear/res/layout/single_page_nav_drawer_2_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_2_item.xml
index cbdbb24..63dbbe6 100644
--- a/wear/res/layout/single_page_nav_drawer_2_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_2_item.xml
@@ -21,24 +21,24 @@
     android:clipChildren="false">
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
+        android:id="@+id/ws_nav_drawer_icon_0"
         android:layout_alignParentStart="true"
         android:layout_centerVertical="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_2_items"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_2_items"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
+        android:id="@+id/ws_nav_drawer_icon_1"
         android:layout_alignParentEnd="true"
         android:layout_centerVertical="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_2_items"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_2_items"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <TextView
-        android:id="@+id/wearable_support_nav_drawer_text"
-        android:layout_below="@id/wearable_support_nav_drawer_icon_1"
-        style="@style/SinglePageNavDrawerTextStyle"/>
+        android:id="@+id/ws_nav_drawer_text"
+        android:layout_below="@id/ws_nav_drawer_icon_1"
+        style="@style/WsSinglePageNavDrawerTextStyle"/>
 
 </android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_3_item.xml b/wear/res/layout/ws_single_page_nav_drawer_3_item.xml
similarity index 69%
rename from wear/res/layout/single_page_nav_drawer_3_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_3_item.xml
index 5e4fc52..209ec16 100644
--- a/wear/res/layout/single_page_nav_drawer_3_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_3_item.xml
@@ -21,30 +21,30 @@
     android:clipChildren="false">
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
+        android:id="@+id/ws_nav_drawer_icon_0"
         android:layout_alignParentStart="true"
         android:layout_centerVertical="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_3_items"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_3_items"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
+        android:id="@+id/ws_nav_drawer_icon_1"
         android:layout_centerInParent="true"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_2"
+        android:id="@+id/ws_nav_drawer_icon_2"
         android:layout_alignParentEnd="true"
         android:layout_centerVertical="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_3_items"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_3_items"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <TextView
-        android:id="@+id/wearable_support_nav_drawer_text"
-        android:layout_below="@id/wearable_support_nav_drawer_icon_2"
-        style="@style/SinglePageNavDrawerTextStyle"/>
+        android:id="@+id/ws_nav_drawer_text"
+        android:layout_below="@id/ws_nav_drawer_icon_2"
+        style="@style/WsSinglePageNavDrawerTextStyle"/>
 
 </android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_4_item.xml b/wear/res/layout/ws_single_page_nav_drawer_4_item.xml
similarity index 66%
rename from wear/res/layout/single_page_nav_drawer_4_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_4_item.xml
index 4acfdab..1b2c163 100644
--- a/wear/res/layout/single_page_nav_drawer_4_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_4_item.xml
@@ -21,38 +21,38 @@
     android:clipChildren="false">
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
+        android:id="@+id/ws_nav_drawer_icon_0"
         android:layout_alignParentTop="true"
         android:layout_centerHorizontal="true"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_4_items_vertical"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_4_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
+        android:id="@+id/ws_nav_drawer_icon_1"
         android:layout_alignParentStart="true"
         android:layout_centerVertical="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_4_items_horizontal"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_4_items_horizontal"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_2"
+        android:id="@+id/ws_nav_drawer_icon_2"
         android:layout_centerInParent="true"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_3"
+        android:id="@+id/ws_nav_drawer_icon_3"
         android:layout_alignParentEnd="true"
         android:layout_centerVertical="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_4_items_horizontal"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_4_items_horizontal"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <TextView
-        android:id="@+id/wearable_support_nav_drawer_text"
-        android:layout_below="@id/wearable_support_nav_drawer_icon_3"
-        style="@style/SinglePageNavDrawerTextStyle"/>
+        android:id="@+id/ws_nav_drawer_text"
+        android:layout_below="@id/ws_nav_drawer_icon_3"
+        style="@style/WsSinglePageNavDrawerTextStyle"/>
 
 </android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/ws_single_page_nav_drawer_5_item.xml b/wear/res/layout/ws_single_page_nav_drawer_5_item.xml
new file mode 100644
index 0000000..699533d
--- /dev/null
+++ b/wear/res/layout/ws_single_page_nav_drawer_5_item.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false">
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_0"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentTop="true"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_outer_rows"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_5_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle"/>
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_1"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentTop="true"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_outer_rows"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_5_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_2"
+        android:layout_alignParentStart="true"
+        android:layout_centerVertical="true"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_middle_row"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_3"
+        android:layout_centerInParent="true"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_4"
+        android:layout_alignParentEnd="true"
+        android:layout_centerVertical="true"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_5_items_horizontal_middle_row"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <TextView
+        android:id="@+id/ws_nav_drawer_text"
+        android:layout_below="@id/ws_nav_drawer_icon_4"
+        style="@style/WsSinglePageNavDrawerTextStyle"/>
+
+</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_6_item.xml b/wear/res/layout/ws_single_page_nav_drawer_6_item.xml
similarity index 60%
rename from wear/res/layout/single_page_nav_drawer_6_item.xml
rename to wear/res/layout/ws_single_page_nav_drawer_6_item.xml
index fd6cd65..00625a1 100644
--- a/wear/res/layout/single_page_nav_drawer_6_item.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_6_item.xml
@@ -21,56 +21,56 @@
     android:clipChildren="false">
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_0"
+        android:id="@+id/ws_nav_drawer_icon_0"
         android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_6_items_horizontal"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_1"
+        android:id="@+id/ws_nav_drawer_icon_1"
         android:layout_centerHorizontal="true"
         android:layout_alignParentTop="true"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_2"
+        android:id="@+id/ws_nav_drawer_icon_2"
         android:layout_alignParentEnd="true"
         android:layout_alignParentTop="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_6_items_horizontal"
-        app:layout_marginTopPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_3"
+        android:id="@+id/ws_nav_drawer_icon_3"
         android:layout_alignParentStart="true"
         android:layout_alignParentBottom="true"
-        app:layout_marginStartPercent="@fraction/nav_drawer_margin_6_items_horizontal"
-        app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+        app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_4"
+        android:id="@+id/ws_nav_drawer_icon_4"
         android:layout_centerHorizontal="true"
         android:layout_alignParentBottom="true"
-        app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
 
     <android.support.wear.widget.CircledImageView
-        android:id="@+id/wearable_support_nav_drawer_icon_5"
+        android:id="@+id/ws_nav_drawer_icon_5"
         android:layout_alignParentEnd="true"
         android:layout_alignParentBottom="true"
-        app:layout_marginEndPercent="@fraction/nav_drawer_margin_6_items_horizontal"
-        app:layout_marginBottomPercent="@fraction/nav_drawer_margin_6_items_vertical"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_6_items_horizontal"
+        app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_6_items_vertical"
         tools:ignore="ContentDescription"
-        style="@style/SinglePageNavDrawerIconStyle" />
+        style="@style/WsSinglePageNavDrawerIconStyle" />
 
 </android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/ws_single_page_nav_drawer_7_item.xml b/wear/res/layout/ws_single_page_nav_drawer_7_item.xml
new file mode 100644
index 0000000..5daef22
--- /dev/null
+++ b/wear/res/layout/ws_single_page_nav_drawer_7_item.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false">
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_0"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentTop="true"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_1"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentTop="true"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+        app:layout_marginTopPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_2"
+        android:layout_alignParentStart="true"
+        android:layout_centerVertical="true"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_middle_row"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_3"
+        android:layout_centerInParent="true"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_4"
+        android:layout_alignParentEnd="true"
+        android:layout_centerVertical="true"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_middle_row"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_5"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentBottom="true"
+        app:layout_marginStartPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+        app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+    <android.support.wear.widget.CircledImageView
+        android:id="@+id/ws_nav_drawer_icon_6"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentBottom="true"
+        app:layout_marginEndPercent="@fraction/ws_nav_drawer_margin_7_items_horizontal_outer_rows"
+        app:layout_marginBottomPercent="@fraction/ws_nav_drawer_margin_7_items_vertical"
+        tools:ignore="ContentDescription"
+        style="@style/WsSinglePageNavDrawerIconStyle" />
+
+</android.support.percent.PercentRelativeLayout>
diff --git a/wear/res/layout/single_page_nav_drawer_peek_view.xml b/wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
similarity index 78%
rename from wear/res/layout/single_page_nav_drawer_peek_view.xml
rename to wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
index e0ed880..8b11554 100644
--- a/wear/res/layout/single_page_nav_drawer_peek_view.xml
+++ b/wear/res/layout/ws_single_page_nav_drawer_peek_view.xml
@@ -20,13 +20,13 @@
     android:layout_height="wrap_content"
     android:gravity="center"
     android:orientation="vertical"
-    android:paddingTop="@dimen/peek_view_top_padding"
-    android:paddingBottom="@dimen/peek_view_bottom_padding">
+    android:paddingTop="@dimen/ws_peek_view_top_padding"
+    android:paddingBottom="@dimen/ws_peek_view_bottom_padding">
 
     <ImageView
-        android:layout_width="@dimen/peek_view_icon_size"
-        android:layout_height="@dimen/peek_view_icon_size"
-        android:src="@drawable/ic_expand_more_white_22"
+        android:layout_width="@dimen/ws_peek_view_icon_size"
+        android:layout_height="@dimen/ws_peek_view_icon_size"
+        android:src="@drawable/ws_ic_expand_more_white_22"
         android:tint="?android:attr/colorForeground"
         tools:ignore="ContentDescription"/>
 
diff --git a/wear/res/values-sw180dp-notround/dimens.xml b/wear/res/values-sw180dp-notround/dimens.xml
index 87938e5..f6395d3 100644
--- a/wear/res/values-sw180dp-notround/dimens.xml
+++ b/wear/res/values-sw180dp-notround/dimens.xml
@@ -15,11 +15,11 @@
 -->
 <resources>
 
-    <dimen name="action_drawer_item_top_padding">10dp</dimen>
-    <dimen name="action_drawer_item_bottom_padding">10dp</dimen>
-    <dimen name="action_drawer_item_icon_right_margin">12dp</dimen>
-    <dimen name="action_drawer_item_icon_size">40dp</dimen>
-    <dimen name="action_drawer_item_icon_padding">8dp</dimen>
-    <dimen name="action_drawer_item_text_size">16sp</dimen>
+    <dimen name="ws_action_drawer_item_top_padding">10dp</dimen>
+    <dimen name="ws_action_drawer_item_bottom_padding">10dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_right_margin">12dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_size">40dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_padding">8dp</dimen>
+    <dimen name="ws_action_drawer_item_text_size">16sp</dimen>
 
 </resources>
diff --git a/wear/res/values-sw210dp-round/dimens.xml b/wear/res/values-sw210dp-round/dimens.xml
index d6d4ed0..1a2581e 100644
--- a/wear/res/values-sw210dp-round/dimens.xml
+++ b/wear/res/values-sw210dp-round/dimens.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 <resources>
-    <dimen name="action_drawer_item_top_padding">10dp</dimen>
-    <dimen name="action_drawer_item_bottom_padding">10dp</dimen>
-    <dimen name="action_drawer_item_icon_right_margin">12dp</dimen>
-    <dimen name="action_drawer_item_icon_size">40dp</dimen>
-    <dimen name="action_drawer_item_icon_padding">8dp</dimen>
-    <dimen name="action_drawer_item_text_size">16sp</dimen>
+    <dimen name="ws_action_drawer_item_top_padding">10dp</dimen>
+    <dimen name="ws_action_drawer_item_bottom_padding">10dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_right_margin">12dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_size">40dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_padding">8dp</dimen>
+    <dimen name="ws_action_drawer_item_text_size">16sp</dimen>
 </resources>
diff --git a/wear/res/values-sw210dp/dimens.xml b/wear/res/values-sw210dp/dimens.xml
index e8d7afc..8f69e0b 100644
--- a/wear/res/values-sw210dp/dimens.xml
+++ b/wear/res/values-sw210dp/dimens.xml
@@ -15,8 +15,8 @@
 -->
 <resources>
 
-    <dimen name="nav_drawer_text_size">14sp</dimen>
-    <dimen name="nav_drawer_single_page_icon_size">32dp</dimen>
-    <dimen name="nav_drawer_single_page_circle_radius">27dp</dimen>
+    <dimen name="ws_nav_drawer_text_size">14sp</dimen>
+    <dimen name="ws_nav_drawer_single_page_icon_size">32dp</dimen>
+    <dimen name="ws_nav_drawer_single_page_circle_radius">27dp</dimen>
 
 </resources>
diff --git a/wear/res/values-v20/styles.xml b/wear/res/values-v20/styles.xml
index aa442f7..2104f6d 100644
--- a/wear/res/values-v20/styles.xml
+++ b/wear/res/values-v20/styles.xml
@@ -15,20 +15,20 @@
 -->
 <resources>
 
-    <style name="PageIndicatorViewStyle">
-        <item name="pageIndicatorDotSpacing">7.8dp</item>
-        <item name="pageIndicatorDotRadius">2.1dp</item>
-        <item name="pageIndicatorDotRadiusSelected">3.1dp</item>
-        <item name="pageIndicatorDotColor">?android:attr/colorForeground</item>
-        <item name="pageIndicatorDotColorSelected">?android:attr/colorForeground</item>
-        <item name="pageIndicatorDotFadeOutDelay">1000</item>
-        <item name="pageIndicatorDotFadeOutDuration">250</item>
-        <item name="pageIndicatorDotFadeInDuration">100</item>
-        <item name="pageIndicatorDotFadeWhenIdle">true</item>
-        <item name="pageIndicatorDotShadowColor">#66000000</item>
-        <item name="pageIndicatorDotShadowRadius">1dp</item>
-        <item name="pageIndicatorDotShadowDx">0.5dp</item>
-        <item name="pageIndicatorDotShadowDy">0.5dp</item>
+    <style name="WsPageIndicatorViewStyle">
+        <item name="dotSpacing">7.8dp</item>
+        <item name="dotRadius">2.1dp</item>
+        <item name="dotRadiusSelected">3.1dp</item>
+        <item name="dotColor">?android:attr/colorForeground</item>
+        <item name="dotColorSelected">?android:attr/colorForeground</item>
+        <item name="dotFadeOutDelay">1000</item>
+        <item name="dotFadeOutDuration">250</item>
+        <item name="dotFadeInDuration">100</item>
+        <item name="dotFadeWhenIdle">true</item>
+        <item name="dotShadowColor">#66000000</item>
+        <item name="dotShadowRadius">1dp</item>
+        <item name="dotShadowDx">0.5dp</item>
+        <item name="dotShadowDy">0.5dp</item>
     </style>
 
 </resources>
diff --git a/wear/res/values-v23/styles.xml b/wear/res/values-v23/styles.xml
index 49a94eb..6bb1a51 100644
--- a/wear/res/values-v23/styles.xml
+++ b/wear/res/values-v23/styles.xml
@@ -14,15 +14,15 @@
      limitations under the License.
 -->
 <resources>
-    <style name="WearableActionDrawerItemText">
+    <style name="WsWearableActionDrawerItemText">
         <item name="android:layout_gravity">center_vertical</item>
         <item name="android:ellipsize">end</item>
         <item name="android:fontFamily">sans-serif-condensed-light</item>
         <item name="android:maxLines">3</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
-        <item name="android:textSize">@dimen/action_drawer_item_text_size</item>
+        <item name="android:textSize">@dimen/ws_action_drawer_item_text_size</item>
     </style>
-    <style name="WearableActionDrawerTitleText" parent="android:TextAppearance.Material.Subhead">
+    <style name="WsWearableActionDrawerTitleText" parent="android:TextAppearance.Material.Subhead">
         <item name="android:alpha">0.7</item>
     </style>
 </resources>
diff --git a/wear/res/values/attrs.xml b/wear/res/values/attrs.xml
index 673fda5..8688a52 100644
--- a/wear/res/values/attrs.xml
+++ b/wear/res/values/attrs.xml
@@ -101,70 +101,70 @@
 
     <declare-styleable name="PageIndicatorView">
         <!-- Sets the distance between dots. -->
-        <attr name="pageIndicatorDotSpacing" format="dimension" />
+        <attr name="dotSpacing" format="dimension" />
         <!-- Sets the radius of a dot when it is not selected. -->
-        <attr name="pageIndicatorDotRadius" format="dimension" />
+        <attr name="dotRadius" format="dimension" />
         <!-- Sets the radius of a dot when it is selected. -->
-        <attr name="pageIndicatorDotRadiusSelected" format="dimension" />
+        <attr name="dotRadiusSelected" format="dimension" />
         <!-- Sets the color of a dot when it is not selected. -->
-        <attr name="pageIndicatorDotColor" format="color" />
+        <attr name="dotColor" format="color" />
         <!-- Sets the color of a dot when it is selected. -->
-        <attr name="pageIndicatorDotColorSelected" format="color" />
+        <attr name="dotColorSelected" format="color" />
         <!-- Sets whether the dots should fade out after inactivity. -->
-        <attr name="pageIndicatorDotFadeWhenIdle" format="boolean" />
+        <attr name="dotFadeWhenIdle" format="boolean" />
         <!-- Sets the delay between the pager arriving at an idle state, and the fade out animation
              beginning, in milliseconds. -->
-        <attr name="pageIndicatorDotFadeOutDelay" format="integer" />
+        <attr name="dotFadeOutDelay" format="integer" />
         <!-- Sets the duration of the fade out animation. -->
-        <attr name="pageIndicatorDotFadeOutDuration" format="integer" />
+        <attr name="dotFadeOutDuration" format="integer" />
         <!-- Sets the duration of the fade in animation. -->
-        <attr name="pageIndicatorDotFadeInDuration" format="integer" />
+        <attr name="dotFadeInDuration" format="integer" />
         <!-- Sets the shadow color. -->
-        <attr name="pageIndicatorDotShadowColor" format="color" />
+        <attr name="dotShadowColor" format="color" />
         <!-- Sets the shadow radius. -->
-        <attr name="pageIndicatorDotShadowRadius" format="dimension" />
+        <attr name="dotShadowRadius" format="dimension" />
         <!-- Sets the horizontal shadow offset. -->
-        <attr name="pageIndicatorDotShadowDx" format="dimension" />
+        <attr name="dotShadowDx" format="dimension" />
         <!-- Sets the vertical shadow offset. -->
-        <attr name="pageIndicatorDotShadowDy" format="dimension" />
+        <attr name="dotShadowDy" format="dimension" />
     </declare-styleable>
 
     <declare-styleable name="CircledImageView">
         <attr name="android:src" />
         <!-- Sets the color of the circle. -->
-        <attr name="circle_color" format="color" />
+        <attr name="background_color" format="color" />
         <!-- Sets the radius of the circle. -->
-        <attr name="circle_radius" format="dimension" />
+        <attr name="background_radius" format="dimension" />
         <!-- Sets the radius of the circle while the circle is being pressed. -->
-        <attr name="circle_radius_pressed" format="dimension" />
+        <attr name="background_radius_pressed" format="dimension" />
         <!-- Sets the width of the border. -->
-        <attr name="circle_border_width" format="dimension" />
+        <attr name="background_border_width" format="dimension" />
         <!-- Sets the color of the border. -->
-        <attr name="circle_border_color" format="color" />
+        <attr name="background_border_color" format="color" />
         <!-- Sets the stroke cap for the border around the circle. -->
-        <attr name="circle_border_cap" format="enum">
+        <attr name="background_border_cap" format="enum">
             <enum name="butt" value="0" />
             <enum name="round" value="1" />
             <enum name="square" value="2" />
         </attr>
         <!-- Sets the padding between the edge of the circle and the start of the image. -->
-        <attr name="circle_padding" format="dimension" />
+        <attr name="img_padding" format="dimension" />
         <!-- Sets the width of the shadow. -->
-        <attr name="shadow_width" format="dimension" />
+        <attr name="background_shadow_width" format="dimension" />
         <!-- Sets the percentage of the circle which the image should occupy. -->
-        <attr name="image_circle_percentage" format="dimension" />
+        <attr name="img_circle_percentage" format="dimension" />
         <!-- Sets the percentage of the circle which the image should should be offset
              horizontally. -->
-        <attr name="image_horizontal_offcenter_percentage" format="dimension" />
+        <attr name="img_horizontal_offset_percentage" format="dimension" />
         <!-- Sets the tint color of the image. -->
-        <attr name="image_tint" format="color" />
+        <attr name="img_tint" format="color" />
         <!-- Sets the radius of the circle to be a percentage of the largest dimension of the
              view. -->
-        <attr name="circle_radius_percent" format="fraction" />
+        <attr name="background_radius_percent" format="fraction" />
         <!-- Sets the circle radius when pressed. -->
-        <attr name="circle_radius_pressed_percent" format="fraction" />
+        <attr name="background_radius_pressed_percent" format="fraction" />
         <!-- Sets which dimension to use if the image isn't square. -->
-        <attr name="square_dimen" format="enum">
+        <attr name="clip_dimen" format="enum">
             <enum name="none" value="0" />
             <enum name="height" value="1" />
             <enum name="width" value="2" />
diff --git a/wear/res/values/dimens.xml b/wear/res/values/dimens.xml
index c39fc77..4e5496d 100644
--- a/wear/res/values/dimens.xml
+++ b/wear/res/values/dimens.xml
@@ -15,50 +15,52 @@
 -->
 <resources>
     <!-- Values for the WearableRecyclerView. -->
-    <dimen name="wrv_curve_default_x_offset">24dp</dimen>
+    <dimen name="ws_wrv_curve_default_x_offset">24dp</dimen>
 
     <!-- Values for WearableDrawerView. -->
-    <dimen name="wearable_drawer_view_elevation">12dp</dimen>
+    <dimen name="ws_wearable_drawer_view_elevation">12dp</dimen>
 
     <!-- Values for WearableActionDrawerView. -->
-    <item name="action_drawer_item_first_item_top_padding" type="fraction">15%</item>
-    <item name="action_drawer_item_last_item_bottom_padding" type="fraction">15%</item>
-    <item name="action_drawer_item_left_padding" type="fraction">15%</item>
-    <item name="action_drawer_item_right_padding" type="fraction">10%</item>
-    <dimen name="action_drawer_item_top_padding">8dp</dimen>
-    <dimen name="action_drawer_item_bottom_padding">8dp</dimen>
-    <dimen name="action_drawer_item_icon_right_margin">8dp</dimen>
-    <dimen name="action_drawer_item_icon_size">36dp</dimen>
-    <dimen name="action_drawer_item_icon_padding">7dp</dimen>
-    <dimen name="action_drawer_item_text_size">14sp</dimen>
-    <dimen name="action_drawer_peek_view_height">43dp</dimen>
-    <dimen name="action_drawer_peek_top_padding">2dp</dimen>
-    <dimen name="action_drawer_expand_icon_top_margin">-3dp</dimen>
+    <item name="ws_action_drawer_item_first_item_top_padding" type="fraction">15%</item>
+    <item name="ws_action_drawer_item_last_item_bottom_padding" type="fraction">15%</item>
+    <item name="ws_action_drawer_item_left_padding" type="fraction">15%</item>
+    <item name="ws_action_drawer_item_right_padding" type="fraction">10%</item>
+    <dimen name="ws_action_drawer_item_top_padding">8dp</dimen>
+    <dimen name="ws_action_drawer_item_bottom_padding">8dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_right_margin">8dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_size">36dp</dimen>
+    <dimen name="ws_action_drawer_item_icon_padding">7dp</dimen>
+    <dimen name="ws_action_drawer_item_text_size">14sp</dimen>
+    <dimen name="ws_action_drawer_peek_view_height">43dp</dimen>
+    <dimen name="ws_action_drawer_peek_top_padding">2dp</dimen>
+    <dimen name="ws_action_drawer_expand_icon_top_margin">-3dp</dimen>
 
     <!-- Dimensions for the single page WearableNavigationDrawerView. -->
-    <dimen name="nav_drawer_single_page_icon_size">28dp</dimen>
-    <dimen name="nav_drawer_single_page_icon_padding">6dp</dimen>
-    <dimen name="nav_drawer_single_page_circle_radius">24dp</dimen>
-    <dimen name="nav_drawer_text_size">12sp</dimen>
-    <fraction name="nav_drawer_text_margin">13%</fraction>
-    <fraction name="nav_drawer_margin_2_items">20%</fraction>
-    <fraction name="nav_drawer_margin_3_items">16%</fraction>
-    <fraction name="nav_drawer_margin_4_items_vertical">16.9%</fraction>
-    <fraction name="nav_drawer_margin_4_items_horizontal">13%</fraction>
-    <fraction name="nav_drawer_margin_5_items_horizontal_outer_rows">27.4%</fraction>
-    <fraction name="nav_drawer_margin_5_items_horizontal_middle_row">13%</fraction>
-    <fraction name="nav_drawer_margin_5_items_vertical">16.9%</fraction>
-    <fraction name="nav_drawer_margin_6_items_horizontal">16%</fraction>
-    <fraction name="nav_drawer_margin_6_items_vertical">26.8%</fraction>
-    <fraction name="nav_drawer_margin_7_items_horizontal_outer_rows">27.4%</fraction>
-    <fraction name="nav_drawer_margin_7_items_horizontal_middle_row">13%</fraction>
-    <fraction name="nav_drawer_margin_7_items_vertical">16.9%</fraction>
+    <dimen name="ws_nav_drawer_single_page_icon_size">28dp</dimen>
+    <dimen name="ws_nav_drawer_single_page_icon_padding">6dp</dimen>
+    <dimen name="ws_nav_drawer_single_page_circle_radius">24dp</dimen>
+    <dimen name="ws_nav_drawer_text_size">12sp</dimen>
+    <fraction name="ws_nav_drawer_text_margin">13%</fraction>
+    <fraction name="ws_nav_drawer_margin_2_items">20%</fraction>
+    <fraction name="ws_nav_drawer_margin_3_items">16%</fraction>
+    <fraction name="ws_nav_drawer_margin_4_items_vertical">16.9%</fraction>
+    <fraction name="ws_nav_drawer_margin_4_items_horizontal">13%</fraction>
+    <fraction name="ws_nav_drawer_margin_5_items_horizontal_outer_rows">27.4%</fraction>
+    <fraction name="ws_nav_drawer_margin_5_items_horizontal_middle_row">13%</fraction>
+    <fraction name="ws_nav_drawer_margin_5_items_vertical">16.9%</fraction>
+    <fraction name="ws_nav_drawer_margin_6_items_horizontal">16%</fraction>
+    <fraction name="ws_nav_drawer_margin_6_items_vertical">26.8%</fraction>
+    <fraction name="ws_nav_drawer_margin_7_items_horizontal_outer_rows">27.4%</fraction>
+    <fraction name="ws_nav_drawer_margin_7_items_horizontal_middle_row">13%</fraction>
+    <fraction name="ws_nav_drawer_margin_7_items_vertical">16.9%</fraction>
 
-    <dimen name="peek_view_top_padding">8dp</dimen>
-    <dimen name="peek_view_bottom_padding">8dp</dimen>
-    <dimen name="peek_view_icon_size">22dp</dimen>
+    <dimen name="ws_peek_view_top_padding">8dp</dimen>
+    <dimen name="ws_peek_view_bottom_padding">8dp</dimen>
+    <dimen name="ws_peek_view_icon_size">22dp</dimen>
 
     <!-- Maximum distance from edge to consider an edge drag. This should be the sum of the peek
          view's top padding, bottom padding, and icon size. -->
-    <dimen name="drawer_view_edge_size">38dp</dimen>
+    <dimen name="ws_drawer_view_edge_size">38dp</dimen>
+    <!-- Dimensions for the wearable switch. -->
+    <dimen name="ws_switch_size">40dp</dimen>
 </resources>
diff --git a/wear/res/values/ids.xml b/wear/res/values/ids.xml
index 881e52a..8a7324e 100644
--- a/wear/res/values/ids.xml
+++ b/wear/res/values/ids.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <resources>
-    <item name="wearable_support_navigation_drawer_view_pager" type="id" />
+    <item name="ws_navigation_drawer_view_pager" type="id" />
 </resources>
diff --git a/wear/res/values/strings.xml b/wear/res/values/strings.xml
index 4d50ddf..3bbb78c 100644
--- a/wear/res/values/strings.xml
+++ b/wear/res/values/strings.xml
@@ -15,8 +15,8 @@
 -->
 <resources>
     <!-- String describing the navigation drawer which is read aloud when focused using accessibility gestures [CHAR LIMIT=35] -->
-    <string name="navigation_drawer_content_description">Navigation drawer</string>
+    <string name="ws_navigation_drawer_content_description">Navigation drawer</string>
 
     <!-- String describing the action drawer which is read aloud when focused using accessibility gestures [CHAR LIMIT=35] -->
-    <string name="action_drawer_content_description">Action drawer</string>
+    <string name="ws_action_drawer_content_description">Action drawer</string>
 </resources>
diff --git a/wear/res/values/styles.xml b/wear/res/values/styles.xml
index 706df13..c0036f1 100644
--- a/wear/res/values/styles.xml
+++ b/wear/res/values/styles.xml
@@ -14,27 +14,41 @@
      limitations under the License.
 -->
 <resources>
-    <style name="SinglePageNavDrawerIconStyle">
-        <item name="android:layout_height">@dimen/nav_drawer_single_page_icon_size</item>
-        <item name="android:layout_width">@dimen/nav_drawer_single_page_icon_size</item>
-        <item name="android:padding">@dimen/nav_drawer_single_page_icon_padding</item>
+    <style name="WsSinglePageNavDrawerIconStyle">
+        <item name="android:layout_height">@dimen/ws_nav_drawer_single_page_icon_size</item>
+        <item name="android:layout_width">@dimen/ws_nav_drawer_single_page_icon_size</item>
+        <item name="android:padding">@dimen/ws_nav_drawer_single_page_icon_padding</item>
         <item name="android:clipToPadding">false</item>
-        <item name="circle_radius">@dimen/nav_drawer_single_page_circle_radius</item>
-        <item name="circle_color">#33ffffff</item>
+        <item name="background_radius">@dimen/ws_nav_drawer_single_page_circle_radius</item>
+        <item name="background_color">#33ffffff</item>
     </style>
-    <style name="SinglePageNavDrawerTextStyle">
+    <style name="WsSinglePageNavDrawerTextStyle">
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:fontFamily">sans-serif-condensed</item>
-        <item name="android:textSize">@dimen/nav_drawer_text_size</item>
+        <item name="android:textSize">@dimen/ws_nav_drawer_text_size</item>
         <item name="android:gravity">center</item>
         <item name="android:maxLines">2</item>
-        <item name="layout_marginTopPercent">@fraction/nav_drawer_text_margin</item>
-        <item name="layout_marginStartPercent">@fraction/nav_drawer_text_margin</item>
-        <item name="layout_marginEndPercent">@fraction/nav_drawer_text_margin</item>
+        <item name="layout_marginTopPercent">@fraction/ws_nav_drawer_text_margin</item>
+        <item name="layout_marginStartPercent">@fraction/ws_nav_drawer_text_margin</item>
+        <item name="layout_marginEndPercent">@fraction/ws_nav_drawer_text_margin</item>
     </style>
-    <style name="Widget.Wearable.WearableDrawerView" parent="">
-        <item name="android:elevation">@dimen/wearable_drawer_view_elevation</item>
+    <style name="Widget.Wear.WearableDrawerView" parent="">
+        <item name="android:elevation">@dimen/ws_wearable_drawer_view_elevation</item>
         <item name="android:background">?android:attr/colorBackgroundFloating</item>
     </style>
+    <style name="Widget.Wear.RoundSwitch"
+            parent="@android:style/Widget.Material.CompoundButton.Switch">
+        <item name="android:layout_width">@dimen/ws_switch_size</item>
+        <item name="android:layout_height">@dimen/ws_switch_size</item>
+        <item name="android:switchMinWidth">@dimen/ws_switch_size</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:thumb">@drawable/ws_switch_thumb_material_anim</item>
+        <item name="android:thumbTint">@color/ws_switch_thumb_color_material</item>
+        <item name="android:thumbTintMode">multiply</item>
+        <item name="android:track">@drawable/ws_switch_track_mtrl</item>
+        <item name="android:trackTint">@color/ws_switch_track_color_material</item>
+        <item name="android:background">@empty</item>
+        <item name="android:showText">false</item>
+    </style>
 </resources>
diff --git a/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java b/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
index 8a65b57..9056845 100644
--- a/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
+++ b/wear/src/android/support/wear/internal/widget/drawer/MultiPageUi.java
@@ -59,16 +59,16 @@
         mPresenter = presenter;
 
         LayoutInflater inflater = LayoutInflater.from(drawer.getContext());
-        final View content =
-                inflater.inflate(R.layout.navigation_drawer_view, drawer, false /* attachToRoot */);
+        final View content = inflater.inflate(R.layout.ws_navigation_drawer_view, drawer,
+                false /* attachToRoot */);
 
         mNavigationPager =
                 (ViewPager) content
-                        .findViewById(R.id.wearable_support_navigation_drawer_view_pager);
+                        .findViewById(R.id.ws_navigation_drawer_view_pager);
         mPageIndicatorView =
                 (PageIndicatorView)
                         content.findViewById(
-                                R.id.wearable_support_navigation_drawer_page_indicator);
+                                R.id.ws_navigation_drawer_page_indicator);
 
         drawer.setDrawerContent(content);
     }
@@ -138,13 +138,13 @@
             // of this method. Attaching to root will cause view to point to container instead.
             final View view =
                     LayoutInflater.from(container.getContext())
-                            .inflate(R.layout.navigation_drawer_item_view, container, false);
+                            .inflate(R.layout.ws_navigation_drawer_item_view, container, false);
             container.addView(view);
             final ImageView iconView =
                     (ImageView) view
-                            .findViewById(R.id.wearable_support_navigation_drawer_item_icon);
+                            .findViewById(R.id.ws_navigation_drawer_item_icon);
             final TextView textView =
-                    (TextView) view.findViewById(R.id.wearable_support_navigation_drawer_item_text);
+                    (TextView) view.findViewById(R.id.ws_navigation_drawer_item_text);
             iconView.setImageDrawable(mAdapter.getItemDrawable(position));
             textView.setText(mAdapter.getItemText(position));
             return view;
diff --git a/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java b/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
index 9a834eb..f3a4290 100644
--- a/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
+++ b/wear/src/android/support/wear/internal/widget/drawer/SinglePageUi.java
@@ -44,26 +44,26 @@
     @IdRes
     private static final int[] SINGLE_PAGE_BUTTON_IDS =
             new int[]{
-                    R.id.wearable_support_nav_drawer_icon_0,
-                    R.id.wearable_support_nav_drawer_icon_1,
-                    R.id.wearable_support_nav_drawer_icon_2,
-                    R.id.wearable_support_nav_drawer_icon_3,
-                    R.id.wearable_support_nav_drawer_icon_4,
-                    R.id.wearable_support_nav_drawer_icon_5,
-                    R.id.wearable_support_nav_drawer_icon_6,
+                    R.id.ws_nav_drawer_icon_0,
+                    R.id.ws_nav_drawer_icon_1,
+                    R.id.ws_nav_drawer_icon_2,
+                    R.id.ws_nav_drawer_icon_3,
+                    R.id.ws_nav_drawer_icon_4,
+                    R.id.ws_nav_drawer_icon_5,
+                    R.id.ws_nav_drawer_icon_6,
             };
 
     @LayoutRes
     private static final int[] SINGLE_PAGE_LAYOUT_RES =
             new int[]{
                     0,
-                    R.layout.single_page_nav_drawer_1_item,
-                    R.layout.single_page_nav_drawer_2_item,
-                    R.layout.single_page_nav_drawer_3_item,
-                    R.layout.single_page_nav_drawer_4_item,
-                    R.layout.single_page_nav_drawer_5_item,
-                    R.layout.single_page_nav_drawer_6_item,
-                    R.layout.single_page_nav_drawer_7_item,
+                    R.layout.ws_single_page_nav_drawer_1_item,
+                    R.layout.ws_single_page_nav_drawer_2_item,
+                    R.layout.ws_single_page_nav_drawer_3_item,
+                    R.layout.ws_single_page_nav_drawer_4_item,
+                    R.layout.ws_single_page_nav_drawer_5_item,
+                    R.layout.ws_single_page_nav_drawer_6_item,
+                    R.layout.ws_single_page_nav_drawer_7_item,
             };
 
     private final WearableNavigationDrawerView mDrawer;
@@ -108,10 +108,10 @@
         View content = inflater.inflate(layoutRes, mDrawer, false /* attachToRoot */);
         final View peek =
                 inflater.inflate(
-                        R.layout.single_page_nav_drawer_peek_view, mDrawer,
+                        R.layout.ws_single_page_nav_drawer_peek_view, mDrawer,
                         false /* attachToRoot */);
 
-        mTextView = (TextView) content.findViewById(R.id.wearable_support_nav_drawer_text);
+        mTextView = (TextView) content.findViewById(R.id.ws_nav_drawer_text);
         mSinglePageImageViews = new CircledImageView[count];
         for (int i = 0; i < count; i++) {
             mSinglePageImageViews[i] = (CircledImageView) content
diff --git a/wear/src/android/support/wear/widget/CircledImageView.java b/wear/src/android/support/wear/widget/CircledImageView.java
index 413b913..e21a1ab 100644
--- a/wear/src/android/support/wear/widget/CircledImageView.java
+++ b/wear/src/android/support/wear/widget/CircledImageView.java
@@ -143,54 +143,55 @@
             mDrawable = mDrawable.mutate();
         }
 
-        mCircleColor = a.getColorStateList(R.styleable.CircledImageView_circle_color);
+        mCircleColor = a.getColorStateList(R.styleable.CircledImageView_background_color);
         if (mCircleColor == null) {
             mCircleColor = ColorStateList.valueOf(android.R.color.darker_gray);
         }
 
-        mCircleRadius = a.getDimension(R.styleable.CircledImageView_circle_radius, 0);
+        mCircleRadius = a.getDimension(R.styleable.CircledImageView_background_radius, 0);
         mInitialCircleRadius = mCircleRadius;
-        mCircleRadiusPressed =
-                a.getDimension(R.styleable.CircledImageView_circle_radius_pressed, mCircleRadius);
+        mCircleRadiusPressed = a.getDimension(
+                R.styleable.CircledImageView_background_radius_pressed, mCircleRadius);
         mCircleBorderColor = a
-                .getColor(R.styleable.CircledImageView_circle_border_color, Color.BLACK);
+                .getColor(R.styleable.CircledImageView_background_border_color, Color.BLACK);
         mCircleBorderCap =
-                Paint.Cap.values()[a.getInt(R.styleable.CircledImageView_circle_border_cap, 0)];
-        mCircleBorderWidth = a.getDimension(R.styleable.CircledImageView_circle_border_width, 0);
+                Paint.Cap.values()[a.getInt(R.styleable.CircledImageView_background_border_cap, 0)];
+        mCircleBorderWidth = a.getDimension(
+                R.styleable.CircledImageView_background_border_width, 0);
 
         if (mCircleBorderWidth > 0) {
             // The border arc is drawn from the middle of the arc - take that into account.
             mRadiusInset += mCircleBorderWidth / 2;
         }
 
-        float circlePadding = a.getDimension(R.styleable.CircledImageView_circle_padding, 0);
+        float circlePadding = a.getDimension(R.styleable.CircledImageView_img_padding, 0);
         if (circlePadding > 0) {
             mRadiusInset += circlePadding;
         }
 
         mImageCirclePercentage = a
-                .getFloat(R.styleable.CircledImageView_image_circle_percentage, 0f);
+                .getFloat(R.styleable.CircledImageView_img_circle_percentage, 0f);
 
         mImageHorizontalOffcenterPercentage =
-                a.getFloat(R.styleable.CircledImageView_image_horizontal_offcenter_percentage, 0f);
+                a.getFloat(R.styleable.CircledImageView_img_horizontal_offset_percentage, 0f);
 
-        if (a.hasValue(R.styleable.CircledImageView_image_tint)) {
-            mImageTint = a.getColor(R.styleable.CircledImageView_image_tint, 0);
+        if (a.hasValue(R.styleable.CircledImageView_img_tint)) {
+            mImageTint = a.getColor(R.styleable.CircledImageView_img_tint, 0);
         }
 
-        if (a.hasValue(R.styleable.CircledImageView_square_dimen)) {
-            mSquareDimen = a.getInt(R.styleable.CircledImageView_square_dimen, SQUARE_DIMEN_NONE);
+        if (a.hasValue(R.styleable.CircledImageView_clip_dimen)) {
+            mSquareDimen = a.getInt(R.styleable.CircledImageView_clip_dimen, SQUARE_DIMEN_NONE);
         }
 
         mCircleRadiusPercent =
-                a.getFraction(R.styleable.CircledImageView_circle_radius_percent, 1, 1, 0f);
+                a.getFraction(R.styleable.CircledImageView_background_radius_percent, 1, 1, 0f);
 
         mCircleRadiusPressedPercent =
                 a.getFraction(
-                        R.styleable.CircledImageView_circle_radius_pressed_percent, 1, 1,
+                        R.styleable.CircledImageView_background_radius_pressed_percent, 1, 1,
                         mCircleRadiusPercent);
 
-        float shadowWidth = a.getDimension(R.styleable.CircledImageView_shadow_width, 0);
+        float shadowWidth = a.getDimension(R.styleable.CircledImageView_background_shadow_width, 0);
 
         a.recycle();
 
diff --git a/wear/src/android/support/wear/widget/CurvingLayoutCallback.java b/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
index f6eed46..275f1f8 100644
--- a/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
+++ b/wear/src/android/support/wear/widget/CurvingLayoutCallback.java
@@ -53,7 +53,7 @@
         mPathMeasure = new PathMeasure();
         mIsScreenRound = context.getResources().getConfiguration().isScreenRound();
         mXCurveOffset = context.getResources().getDimensionPixelSize(
-                R.dimen.wrv_curve_default_x_offset);
+                R.dimen.ws_wrv_curve_default_x_offset);
     }
 
     @Override
diff --git a/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java b/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
index 7317c21..bd2dded 100644
--- a/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
+++ b/wear/src/android/support/wear/widget/drawer/PageIndicatorView.java
@@ -96,28 +96,28 @@
                 getContext()
                         .obtainStyledAttributes(
                                 attrs, R.styleable.PageIndicatorView, defStyleAttr,
-                                R.style.PageIndicatorViewStyle);
+                                R.style.WsPageIndicatorViewStyle);
 
         mDotSpacing =
-                a.getDimensionPixelOffset(R.styleable.PageIndicatorView_pageIndicatorDotSpacing, 0);
-        mDotRadius = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotRadius, 0);
+                a.getDimensionPixelOffset(R.styleable.PageIndicatorView_dotSpacing, 0);
+        mDotRadius = a.getDimension(R.styleable.PageIndicatorView_dotRadius, 0);
         mDotRadiusSelected =
-                a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotRadiusSelected, 0);
-        mDotColor = a.getColor(R.styleable.PageIndicatorView_pageIndicatorDotColor, 0);
+                a.getDimension(R.styleable.PageIndicatorView_dotRadiusSelected, 0);
+        mDotColor = a.getColor(R.styleable.PageIndicatorView_dotColor, 0);
         mDotColorSelected = a
-                .getColor(R.styleable.PageIndicatorView_pageIndicatorDotColorSelected, 0);
-        mDotFadeOutDelay = a.getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeOutDelay, 0);
+                .getColor(R.styleable.PageIndicatorView_dotColorSelected, 0);
+        mDotFadeOutDelay = a.getInt(R.styleable.PageIndicatorView_dotFadeOutDelay, 0);
         mDotFadeOutDuration =
-                a.getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeOutDuration, 0);
+                a.getInt(R.styleable.PageIndicatorView_dotFadeOutDuration, 0);
         mDotFadeInDuration = a
-                .getInt(R.styleable.PageIndicatorView_pageIndicatorDotFadeInDuration, 0);
+                .getInt(R.styleable.PageIndicatorView_dotFadeInDuration, 0);
         mDotFadeWhenIdle =
-                a.getBoolean(R.styleable.PageIndicatorView_pageIndicatorDotFadeWhenIdle, false);
-        mDotShadowDx = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowDx, 0);
-        mDotShadowDy = a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowDy, 0);
+                a.getBoolean(R.styleable.PageIndicatorView_dotFadeWhenIdle, false);
+        mDotShadowDx = a.getDimension(R.styleable.PageIndicatorView_dotShadowDx, 0);
+        mDotShadowDy = a.getDimension(R.styleable.PageIndicatorView_dotShadowDy, 0);
         mDotShadowRadius =
-                a.getDimension(R.styleable.PageIndicatorView_pageIndicatorDotShadowRadius, 0);
-        mDotShadowColor = a.getColor(R.styleable.PageIndicatorView_pageIndicatorDotShadowColor, 0);
+                a.getDimension(R.styleable.PageIndicatorView_dotShadowRadius, 0);
+        mDotShadowColor = a.getColor(R.styleable.PageIndicatorView_dotShadowColor, 0);
         a.recycle();
 
         mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
diff --git a/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
index a663cc2..3074865 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableActionDrawerView.java
@@ -137,20 +137,20 @@
 
         if (!mShowOverflowInPeek) {
             LayoutInflater layoutInflater = LayoutInflater.from(context);
-            View peekView = layoutInflater.inflate(
-                    R.layout.action_drawer_peek_view, getPeekContainer(), false /* attachToRoot */);
+            View peekView = layoutInflater.inflate(R.layout.ws_action_drawer_peek_view,
+                    getPeekContainer(), false /* attachToRoot */);
             setPeekContent(peekView);
             mPeekActionIcon =
                     (ImageView) peekView
-                            .findViewById(R.id.wearable_support_action_drawer_peek_action_icon);
+                            .findViewById(R.id.ws_action_drawer_peek_action_icon);
             mPeekExpandIcon =
                     (ImageView) peekView
-                            .findViewById(R.id.wearable_support_action_drawer_expand_icon);
+                            .findViewById(R.id.ws_action_drawer_expand_icon);
         } else {
             mPeekActionIcon = null;
             mPeekExpandIcon = null;
             getPeekContainer().setContentDescription(
-                    context.getString(R.string.action_drawer_content_description));
+                    context.getString(R.string.ws_action_drawer_content_description));
         }
 
         if (menuRes != 0) {
@@ -164,26 +164,26 @@
         int screenHeightPx = ResourcesUtil.getScreenHeightPx(context);
 
         Resources res = getResources();
-        mTopPadding = res.getDimensionPixelOffset(R.dimen.action_drawer_item_top_padding);
-        mBottomPadding = res.getDimensionPixelOffset(R.dimen.action_drawer_item_bottom_padding);
+        mTopPadding = res.getDimensionPixelOffset(R.dimen.ws_action_drawer_item_top_padding);
+        mBottomPadding = res.getDimensionPixelOffset(R.dimen.ws_action_drawer_item_bottom_padding);
         mLeftPadding =
                 ResourcesUtil.getFractionOfScreenPx(
-                        context, screenWidthPx, R.fraction.action_drawer_item_left_padding);
+                        context, screenWidthPx, R.fraction.ws_action_drawer_item_left_padding);
         mRightPadding =
                 ResourcesUtil.getFractionOfScreenPx(
-                        context, screenWidthPx, R.fraction.action_drawer_item_right_padding);
+                        context, screenWidthPx, R.fraction.ws_action_drawer_item_right_padding);
 
         mFirstItemTopPadding =
                 ResourcesUtil.getFractionOfScreenPx(
                         context, screenHeightPx,
-                        R.fraction.action_drawer_item_first_item_top_padding);
+                        R.fraction.ws_action_drawer_item_first_item_top_padding);
         mLastItemBottomPadding =
                 ResourcesUtil.getFractionOfScreenPx(
                         context, screenHeightPx,
-                        R.fraction.action_drawer_item_last_item_bottom_padding);
+                        R.fraction.ws_action_drawer_item_last_item_bottom_padding);
 
         mIconRightMargin = res
-                .getDimensionPixelOffset(R.dimen.action_drawer_item_icon_right_margin);
+                .getDimensionPixelOffset(R.dimen.ws_action_drawer_item_icon_right_margin);
 
         mActionList = new RecyclerView(context);
         mActionList.setLayoutManager(new LinearLayoutManager(context));
@@ -359,7 +359,7 @@
         TitleViewHolder(View view) {
             super(view);
             this.view = view;
-            textView = (TextView) view.findViewById(R.id.wearable_support_action_drawer_title);
+            textView = (TextView) view.findViewById(R.id.ws_action_drawer_title);
         }
     }
 
@@ -425,14 +425,14 @@
                 case TYPE_TITLE:
                     View titleView =
                             LayoutInflater.from(parent.getContext())
-                                    .inflate(R.layout.action_drawer_title_view, parent, false);
+                                    .inflate(R.layout.ws_action_drawer_title_view, parent, false);
                     return new TitleViewHolder(titleView);
 
                 case TYPE_ACTION:
                 default:
                     View actionView =
                             LayoutInflater.from(parent.getContext())
-                                    .inflate(R.layout.action_drawer_item_view, parent, false);
+                                    .inflate(R.layout.ws_action_drawer_item_view, parent, false);
                     actionView.setOnClickListener(mItemClickListener);
                     return new ActionItemViewHolder(actionView);
             }
@@ -453,9 +453,9 @@
         ActionItemViewHolder(View view) {
             super(view);
             this.view = view;
-            iconView = (ImageView) view.findViewById(R.id.wearable_support_action_drawer_item_icon);
+            iconView = (ImageView) view.findViewById(R.id.ws_action_drawer_item_icon);
             ((LinearLayout.LayoutParams) iconView.getLayoutParams()).setMarginEnd(mIconRightMargin);
-            textView = (TextView) view.findViewById(R.id.wearable_support_action_drawer_item_text);
+            textView = (TextView) view.findViewById(R.id.ws_action_drawer_item_text);
         }
     }
 }
diff --git a/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
index 97aa9f5..0203860 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableDrawerView.java
@@ -149,13 +149,14 @@
     public WearableDrawerView(
             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        LayoutInflater.from(context).inflate(R.layout.wearable_drawer_view, this, true);
+        LayoutInflater.from(context).inflate(R.layout.ws_wearable_drawer_view, this, true);
 
         setClickable(true);
-        setElevation(context.getResources().getDimension(R.dimen.wearable_drawer_view_elevation));
+        setElevation(context.getResources()
+                .getDimension(R.dimen.ws_wearable_drawer_view_elevation));
 
-        mPeekContainer = (ViewGroup) findViewById(R.id.wearable_support_drawer_view_peek_container);
-        mPeekIcon = (ImageView) findViewById(R.id.wearable_support_drawer_view_peek_icon);
+        mPeekContainer = (ViewGroup) findViewById(R.id.ws_drawer_view_peek_container);
+        mPeekIcon = (ImageView) findViewById(R.id.ws_drawer_view_peek_icon);
 
         mPeekContainer.setOnClickListener(
                 new OnClickListener() {
@@ -215,10 +216,10 @@
                             == Gravity.TOP;
             if (isTopDrawer) {
                 peekParams.gravity = Gravity.BOTTOM;
-                mPeekIcon.setImageResource(R.drawable.ic_more_horiz_24dp_wht);
+                mPeekIcon.setImageResource(R.drawable.ws_ic_more_horiz_24dp_wht);
             } else {
                 peekParams.gravity = Gravity.TOP;
-                mPeekIcon.setImageResource(R.drawable.ic_more_vert_24dp_wht);
+                mPeekIcon.setImageResource(R.drawable.ws_ic_more_vert_24dp_wht);
             }
             mPeekContainer.setLayoutParams(peekParams);
         }
@@ -466,7 +467,7 @@
         TypedArray typedArray =
                 context.obtainStyledAttributes(
                         attrs, R.styleable.WearableDrawerView, defStyleAttr,
-                        R.style.Widget_Wearable_WearableDrawerView);
+                        R.style.Widget_Wear_WearableDrawerView);
 
         Drawable background =
                 getDrawable(context, typedArray, R.styleable.WearableDrawerView_android_background);
diff --git a/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java b/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
index 5a17c5c..31cbdd0 100644
--- a/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
+++ b/wear/src/android/support/wear/widget/drawer/WearableNavigationDrawerView.java
@@ -163,7 +163,7 @@
 
         getPeekContainer()
                 .setContentDescription(
-                        context.getString(R.string.navigation_drawer_content_description));
+                        context.getString(R.string.ws_navigation_drawer_content_description));
 
         setOpenOnlyAtTopEnabled(true);
     }
diff --git a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
index 88c89c7..07eaa87 100644
--- a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
+++ b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
@@ -136,7 +136,7 @@
                                 MAX_WAIT_MS));
 
         // THEN the text should display "0".
-        onView(withId(R.id.wearable_support_nav_drawer_text)).check(matches(withText("0")));
+        onView(withId(R.id.ws_nav_drawer_text)).check(matches(withText("0")));
     }
 
     @Test
@@ -151,13 +151,13 @@
                                 MAX_WAIT_MS));
 
         // WHEN the second item is selected
-        onView(withId(R.id.wearable_support_nav_drawer_icon_1)).perform(click());
+        onView(withId(R.id.ws_nav_drawer_icon_1)).perform(click());
 
         // THEN the text should display "1" and it should close.
-        onView(withId(R.id.wearable_support_nav_drawer_text))
+        onView(withId(R.id.ws_nav_drawer_text))
                 .perform(
                         waitForMatchingView(
-                                allOf(withId(R.id.wearable_support_nav_drawer_text), withText("1")),
+                                allOf(withId(R.id.ws_nav_drawer_text), withText("1")),
                                 MAX_WAIT_MS));
         onView(withId(R.id.navigation_drawer))
                 .perform(
@@ -181,7 +181,7 @@
         selectNavItem(navDrawer, 1);
 
         // THEN the text should display "1" and the listener should be notified.
-        onView(withId(R.id.wearable_support_nav_drawer_text))
+        onView(withId(R.id.ws_nav_drawer_text))
                 .check(matches(withText("1")));
         verify(mNavDrawerItemSelectedListener).onItemSelected(1);
     }
@@ -201,7 +201,7 @@
         selectNavItem(navDrawer, 1);
 
         // THEN the text should display "1" and the listener should be notified.
-        onView(allOf(withId(R.id.wearable_support_navigation_drawer_item_text), isDisplayed()))
+        onView(allOf(withId(R.id.ws_navigation_drawer_item_text), isDisplayed()))
                 .check(matches(withText("1")));
         verify(mNavDrawerItemSelectedListener).onItemSelected(1);
     }
@@ -319,7 +319,7 @@
         DrawerTestActivity activity = activityRule.getActivity();
         ImageView peekIconView =
                 (ImageView) activity
-                        .findViewById(R.id.wearable_support_action_drawer_peek_action_icon);
+                        .findViewById(R.id.ws_action_drawer_peek_action_icon);
         // THEN its peek icon should not be null
         assertNotNull(peekIconView.getDrawable());
     }
@@ -340,7 +340,7 @@
         onView(
                 allOf(
                         withParent(withId(R.id.action_drawer)),
-                        withId(R.id.wearable_support_drawer_view_peek_container)))
+                        withId(R.id.ws_drawer_view_peek_container)))
                 .perform(click());
         // THEN its click listener should be notified
         verify(mockClickListener).onMenuItemClick(any(MenuItem.class));