Merge "Disable unused features in AGP" into androidx-master-dev
diff --git a/README.md b/README.md
index b775e48..81ba264 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@
 4. Use `repo` command to initialize the repository.
 
 ```bash
-repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev
+repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev --partial-clone
 ```
 
 5. Now your repository is set to pull only what you need for building and running AndroidX libraries. Download the code (and grab a coffee while we pull down 6GB):
diff --git a/appsearch/appsearch/api/1.0.0-alpha01.txt b/appsearch/appsearch/api/1.0.0-alpha01.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/1.0.0-alpha01.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/api/current.txt b/appsearch/appsearch/api/current.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/current.txt
+++ b/appsearch/appsearch/api/current.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/api/public_plus_experimental_current.txt b/appsearch/appsearch/api/public_plus_experimental_current.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/public_plus_experimental_current.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_current.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/api/restricted_current.txt b/appsearch/appsearch/api/restricted_current.txt
index 74d9356..e2515ba 100644
--- a/appsearch/appsearch/api/restricted_current.txt
+++ b/appsearch/appsearch/api/restricted_current.txt
@@ -1,4 +1,34 @@
 // Signature format: 3.0
+package androidx.appsearch.annotation {
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppSearchDocument {
+    method public abstract String name() default "";
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.CreationTimestampMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Namespace {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Property {
+    method public abstract int indexingType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE;
+    method public abstract String name() default "";
+    method public abstract boolean required() default false;
+    method public abstract int tokenizerType() default androidx.appsearch.app.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Score {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.TtlMillis {
+  }
+
+  @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.FIELD) public static @interface AppSearchDocument.Uri {
+  }
+
+}
+
 package androidx.appsearch.app {
 
   public final class AppSearchBatchResult<KeyType, ValueType> {
@@ -61,6 +91,7 @@
   public class GenericDocument {
     ctor protected GenericDocument(androidx.appsearch.app.GenericDocument);
     method public long getCreationTimestampMillis();
+    method public static int getMaxIndexedProperties();
     method public String getNamespace();
     method public boolean getPropertyBoolean(String);
     method public boolean[]? getPropertyBooleanArray(String);
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/AppSearchDocument.java b/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/AppSearchDocument.java
index fb099d6..d2c7c6a 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/AppSearchDocument.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/AppSearchDocument.java
@@ -16,7 +16,6 @@
 
 package androidx.appsearch.annotation;
 
-import androidx.annotation.RestrictTo;
 import androidx.appsearch.app.AppSearchSchema;
 
 import java.lang.annotation.Documented;
@@ -54,13 +53,10 @@
  * </ol>
  *
  * <p>The class must also have exactly one member annotated with {@link Uri @Uri}.
- *
- * @hide
  */
 @Documented
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.TYPE)
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public @interface AppSearchDocument {
     /**
      * Marks a member field of a document as the document's URI.
@@ -205,9 +201,10 @@
          * <p>This attribute does not apply to properties of a repeated type (e.g. a list).
          *
          * <p>Please make sure you understand the consequences of required fields on
-         * {@link androidx.appsearch.app.AppSearchManager#setSchema schema migration} before setting
+         * {@code androidx.appsearch.app.AppSearchManager#setSchema schema migration} before setting
          * this attribute to {@code true}.
          */
+        // TODO(b/157082794) Linkify AppSearchManager once that API is public.
         boolean required() default false;
     }
 
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/GenericDocument.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/GenericDocument.java
index 73cb5c36..f7ef7c4 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/GenericDocument.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/GenericDocument.java
@@ -22,7 +22,6 @@
 import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
 import androidx.appsearch.exceptions.AppSearchException;
 import androidx.collection.ArrayMap;
 import androidx.core.util.Preconditions;
@@ -68,10 +67,7 @@
      * {@link androidx.appsearch.annotation.AppSearchDocument.Property#indexingType} constant is
      * anything other than {@link
      * androidx.appsearch.app.AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}.
-     *
-     * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public static int getMaxIndexedProperties() {
         return MAX_INDEXED_PROPERTIES;
     }
@@ -441,9 +437,8 @@
      * would be an empty or partially populated result.
      *
      * @param dataClass a non-inner class annotated with
-     *     {@code androidx.appsearch.annotation.AppSearchDocument}.
+     *     {@link androidx.appsearch.annotation.AppSearchDocument}.
      */
-    //TODO(b/157082794): Linkify to AppSearchDocument once that API is public
     @NonNull
     public <T> T toDataClass(@NonNull Class<T> dataClass) throws AppSearchException {
         Preconditions.checkNotNull(dataClass);
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
index 24180c7..4f19d10 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
@@ -106,6 +106,11 @@
     val WEBKIT = LibraryGroup("androidx.webkit", LibraryVersions.WEBKIT)
     val WINDOW = LibraryGroup("androidx.window", null)
     val WORK = LibraryGroup("androidx.work", LibraryVersions.WORK)
+
+    object Compose {
+        val FOUNDATION = LibraryGroup("androidx.compose.foundation", null)
+        val MATERIAL = LibraryGroup("androidx.compose.material", null)
+    }
 }
 
 /**
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 85534fc..d80801a 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -48,9 +48,9 @@
 const val GCM_NETWORK_MANAGER = "com.google.android.gms:play-services-gcm:17.0.0"
 const val GOOGLE_COMPILE_TESTING = "com.google.testing.compile:compile-testing:0.18"
 const val GSON = "com.google.code.gson:gson:2.8.0"
-const val GUAVA_VERSION = "27.0.1-jre"
+const val GUAVA_VERSION = "29.0-jre"
 const val GUAVA = "com.google.guava:guava:$GUAVA_VERSION"
-const val GUAVA_ANDROID_VERSION = "27.0.1-android"
+const val GUAVA_ANDROID_VERSION = "29.0-android"
 const val GUAVA_ANDROID = "com.google.guava:guava:$GUAVA_ANDROID_VERSION"
 const val GUAVA_LISTENABLE_FUTURE = "com.google.guava:listenablefuture:1.0"
 const val GRADLE_INCAP_HELPER = "net.ltgt.gradle.incap:incap:0.2"
diff --git a/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt b/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
index ddc5102..f68997d 100644
--- a/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
@@ -69,6 +69,7 @@
     "lintVitalRelease",
     "partiallyDejetifyArchive",
     "postInstrumentCode",
+    "properties",
     "publishBenchmarkPluginMarkerMavenPublicationToMavenRepository",
     "publishDesktopPublicationToMavenRepository",
     "publishKotlinMultiplatformPublicationToMavenRepository",
diff --git a/busytown/androidx.sh b/busytown/androidx.sh
index 04befb7..51ba5a3 100755
--- a/busytown/androidx.sh
+++ b/busytown/androidx.sh
@@ -8,6 +8,7 @@
 # Run Gradle
 time impl/build.sh --no-daemon listTaskOutputs "$@"
 time impl/build.sh --no-daemon buildOnServer checkExternalLicenses \
+    allProperties \
     -PverifyUpToDate \
     -Pandroidx.coverageEnabled=true \
     -Pandroidx.allWarningsAsErrors --profile "$@"
diff --git a/camera/OWNERS b/camera/OWNERS
index e8dc745..89406eb 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -6,3 +6,4 @@
 xizh@google.com
 charcoalchen@google.com
 scottnien@google.com
+husaynhakeem@google.com
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LiveLiteralTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LiveLiteralTransformTests.kt
index 24057ac..725c136 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LiveLiteralTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LiveLiteralTransformTests.kt
@@ -292,6 +292,24 @@
         """
     }
 
+    @Test
+    fun testEnumEntryMultipleArgs(): Unit = assertKeys(
+        "Int%arg-0%call-%init%%entry-Bar%class-A",
+        "Int%arg-0%call-%init%%entry-Baz%class-A",
+        "Int%arg-0%call-%init%%entry-Foo%class-A",
+        "Int%arg-1%call-%init%%entry-Bar%class-A",
+        "Int%arg-1%call-%init%%entry-Baz%class-A",
+        "Int%arg-1%call-%init%%entry-Foo%class-A"
+    ) {
+        """
+        enum class A(val x: Int, val y: Int) {
+            Foo(1, 2),
+            Bar(2, 3),
+            Baz(3, 4)
+        }
+        """
+    }
+
     fun testCommentsAbove() = assertDurableChange(
         """
             fun Test() {
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/LiveLiteralTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/LiveLiteralTransformer.kt
index 477509f..fe3a143 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/LiveLiteralTransformer.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/LiveLiteralTransformer.kt
@@ -61,6 +61,7 @@
 import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
 import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
 import org.jetbrains.kotlin.ir.expressions.IrElseBranch
+import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall
 import org.jetbrains.kotlin.ir.expressions.IrExpression
 import org.jetbrains.kotlin.ir.expressions.IrLoop
 import org.jetbrains.kotlin.ir.expressions.IrSetField
@@ -431,6 +432,30 @@
         }
     }
 
+    override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
+        val owner = expression.symbol.bindIfNecessary().owner
+        val name = owner.name.asJvmFriendlyString()
+
+        return enter("call-$name") {
+            expression.dispatchReceiver = enter("\$this") {
+                expression.dispatchReceiver?.transform(this, null)
+            }
+            expression.extensionReceiver = enter("\$\$this") {
+                expression.extensionReceiver?.transform(this, null)
+            }
+
+            for (i in 0 until expression.valueArgumentsCount) {
+                val arg = expression.getValueArgument(i)
+                if (arg != null) {
+                    enter("arg-$i") {
+                        expression.putValueArgument(i, arg.transform(this, null))
+                    }
+                }
+            }
+            expression
+        }
+    }
+
     override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
         val owner = expression.symbol.bindIfNecessary().owner
 
diff --git a/compose/compose-runtime/compose-runtime-benchmark/build.gradle b/compose/compose-runtime/compose-runtime-benchmark/build.gradle
index 4218834..580c5ed 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/build.gradle
+++ b/compose/compose-runtime/compose-runtime-benchmark/build.gradle
@@ -51,8 +51,8 @@
     androidTestImplementation(project(":ui:ui-core"))
     androidTestImplementation(project(":ui:ui-text-core"))
     androidTestImplementation(project(":ui:ui-layout"))
-    androidTestImplementation(project(":ui:ui-material"))
-    androidTestImplementation(project(":ui:ui-foundation"))
+    androidTestImplementation(project(":compose:material:material"))
+    androidTestImplementation(project(":compose:foundation:foundation"))
 
     androidTestImplementation(JUNIT)
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/compose/compose-runtime/samples/build.gradle b/compose/compose-runtime/samples/build.gradle
index fb562b8..75915b0 100644
--- a/compose/compose-runtime/samples/build.gradle
+++ b/compose/compose-runtime/samples/build.gradle
@@ -35,7 +35,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/compose/foundation/placeholder.txt b/compose/foundation/placeholder.txt
new file mode 100644
index 0000000..b8f7c1a
--- /dev/null
+++ b/compose/foundation/placeholder.txt
@@ -0,0 +1,4 @@
+This file exists to make sure the directory this is in gets created by git, so that
+settings.gradle can point to this directory and not complain about it missing.
+
+TODO: b/160233169 remove this file once the directory structure is migrated from ui/ to here.
diff --git a/compose/material/placeholder.txt b/compose/material/placeholder.txt
new file mode 100644
index 0000000..b8f7c1a
--- /dev/null
+++ b/compose/material/placeholder.txt
@@ -0,0 +1,4 @@
+This file exists to make sure the directory this is in gets created by git, so that
+settings.gradle can point to this directory and not complain about it missing.
+
+TODO: b/160233169 remove this file once the directory structure is migrated from ui/ to here.
diff --git a/core/core-animation-integration-tests/testapp/src/androidTest/java/androidx/core/animation/AnimatorSetTest.java b/core/core-animation-integration-tests/testapp/src/androidTest/java/androidx/core/animation/AnimatorSetTest.java
index d51c30b..c15630f 100644
--- a/core/core-animation-integration-tests/testapp/src/androidTest/java/androidx/core/animation/AnimatorSetTest.java
+++ b/core/core-animation-integration-tests/testapp/src/androidTest/java/androidx/core/animation/AnimatorSetTest.java
@@ -24,6 +24,8 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import android.util.Property;
+
 import androidx.annotation.NonNull;
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -824,6 +826,60 @@
         mAnimatorSet.cancel();
     }
 
+    @UiThreadTest
+    @Test
+    public void testMultipleAnimatorsSingleProperty() {
+        final SampleTarget target = new SampleTarget();
+        final ObjectAnimator a1 = ObjectAnimator.ofFloat(target, SampleTarget.VALUE, 0f, 1000f);
+        a1.setDuration(1000);
+        a1.setInterpolator(new LinearInterpolator());
+        final ObjectAnimator a2 = ObjectAnimator.ofFloat(target, SampleTarget.VALUE, 1000f, 2000f);
+        a2.setDuration(1000);
+        a2.setStartDelay(1000);
+        a2.setInterpolator(new LinearInterpolator());
+        final AnimatorSet set = new AnimatorSet();
+        set.playTogether(a1, a2);
+
+        set.start();
+
+        final float delta = 0.001f;
+        assertEquals(0f, target.mValue, delta);
+
+        sAnimatorTestRule.advanceTimeBy(500);
+        assertEquals(500f, (float) a1.getAnimatedValue(), delta);
+        assertEquals(500f, target.mValue, delta);
+
+        sAnimatorTestRule.advanceTimeBy(1000);
+        assertEquals(1500f, target.mValue, delta);
+
+        sAnimatorTestRule.advanceTimeBy(5000);
+        assertEquals(2000f, target.mValue, delta);
+        assertFalse(set.isRunning());
+
+        // Rewind
+        set.setCurrentPlayTime(1500);
+        assertEquals(1500f, target.mValue, delta);
+
+        set.setCurrentPlayTime(500);
+        assertEquals(500f, target.mValue, delta);
+    }
+
+    static class SampleTarget {
+
+        static final Property<SampleTarget, Float> VALUE = new FloatProperty<SampleTarget>() {
+            @Override
+            public void setValue(@NonNull SampleTarget object, float value) {
+                object.mValue = value;
+            }
+
+            @Override
+            public Float get(SampleTarget sampleTarget) {
+                return sampleTarget.mValue;
+            }
+        };
+
+        float mValue;
+    }
 
     static class AnimEvent {
         enum EventType {
diff --git a/core/core-animation/src/main/java/androidx/core/animation/AnimatorSet.java b/core/core-animation/src/main/java/androidx/core/animation/AnimatorSet.java
index 6388a13..427bc00 100644
--- a/core/core-animation/src/main/java/androidx/core/animation/AnimatorSet.java
+++ b/core/core-animation/src/main/java/androidx/core/animation/AnimatorSet.java
@@ -791,16 +791,6 @@
             }
         }
 
-        // Seek unfinished animation to the right time.
-        for (int i = 0; i < unfinishedNodes.size(); i++) {
-            Node node = unfinishedNodes.get(i);
-            long playTime = getPlayTimeForNode(currentPlayTime, node, inReverse);
-            if (!inReverse) {
-                playTime -= node.mAnimation.getStartDelay();
-            }
-            node.mAnimation.animateBasedOnPlayTime(playTime, lastPlayTime, inReverse);
-        }
-
         // Seek not yet started animations.
         for (int i = 0; i < mEvents.size(); i++) {
             AnimationEvent event = mEvents.get(i);
@@ -810,6 +800,16 @@
             }
         }
 
+        // Seek unfinished animations to the right time. These should be the last because their
+        // results should not be overwritten by finished or not-yet-started animations.
+        for (int i = 0; i < unfinishedNodes.size(); i++) {
+            Node node = unfinishedNodes.get(i);
+            long playTime = getPlayTimeForNode(currentPlayTime, node, inReverse);
+            if (!inReverse) {
+                playTime -= node.mAnimation.getStartDelay();
+            }
+            node.mAnimation.animateBasedOnPlayTime(playTime, lastPlayTime, inReverse);
+        }
     }
 
     @Override
diff --git a/development/validateComposeModuleMigration.sh b/development/validateComposeModuleMigration.sh
new file mode 100755
index 0000000..5a4ece2
--- /dev/null
+++ b/development/validateComposeModuleMigration.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+#
+#  Copyright (C) 2020 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.
+#
+
+# Temporary script to aid migration from androidx.ui to androidx.compose, by validating artifacts
+# are identical / compatible during the migration
+# Most of the logic here is taken from validateRefactor.sh, and cut down into a less generic script
+# This can be removed after b/160233169 is finished
+
+supportRoot="$(cd $(dirname $0)/.. && pwd)"
+checkoutRoot="$(cd ${supportRoot}/../.. && pwd)"
+
+function die() {
+  echo "$@" >&2
+  exit 1
+}
+
+function usage() {
+  violation="$1"
+  die "
+  Usage: $0 androidx.ui:ui-material androidx.compose.material:material --build
+
+  Builds artifacts for the current commit, and the previous commit, and diffs the output between
+  the old artifact and new artifact, to validate that refactoring a library in Compose has
+  expected changes (such as pom file changes). Also unzips and prints the location of the class
+  files inside the .aar, to facilitate comparing the classes with a tool such as
+  japi-compliance-checker.
+
+  Running without --build will just diff the expected outputs, for cases when you wish to verify
+  multiple artifacts in the same commits.
+  "
+  return 1
+}
+
+function echoAndDo() {
+  echo "$*"
+  eval "$*"
+}
+
+function doBuild() {
+  echoAndDo ./gradlew createArchive --no-daemon --rerun-tasks --offline
+  archiveName="top-of-tree-m2repository-all-0.zip"
+  echoAndDo unzip -q "${tempOutPath}/dist/ui/${archiveName}" -d "${tempOutPath}/dist/ui/${archiveName}.unzipped"
+}
+
+# Ensure at least 2 args
+if (( $# < 2 )); then
+    usage
+fi
+
+oldLibrary=$1
+newLibrary=$2
+shouldBuild=false
+if [[ $3 == "--build" ]]; then
+  shouldBuild=true
+fi
+
+echo old library = $oldLibrary
+echo new library = $newLibrary
+echo building = $shouldBuild
+
+# Replace . and : with / to build the output path from the artifact ID
+oldLibraryRelativePath="${oldLibrary//.//}"
+oldLibraryRelativePath="${oldLibraryRelativePath//://}"
+
+newLibraryRelativePath="${newLibrary//.//}"
+newLibraryRelativePath="${newLibraryRelativePath//://}"
+
+oldOutPath="${checkoutRoot}/out-old"
+newOutPath="${checkoutRoot}/out-new"
+tempOutPath="${checkoutRoot}/out"
+
+if $shouldBuild ; then
+  echo removing out/
+  rm -rf "$oldOutPath" "$newOutPath" "$tempOutPath"
+
+  echo building new commit
+  doBuild
+  mv "$tempOutPath" "$newOutPath"
+
+  echo building previous commit
+
+  echoAndDo git -C "${checkoutRoot}/frameworks/support/ui" checkout "HEAD^"
+  doBuild
+  echoAndDo git -C "${checkoutRoot}/frameworks/support/ui" checkout -
+  mv "$tempOutPath" "$oldOutPath"
+fi
+
+m2repositoryRelativePath="dist/ui/top-of-tree-m2repository-all-0.zip.unzipped/m2repository"
+oldLibraryOutput="${oldOutPath}/${m2repositoryRelativePath}/${oldLibraryRelativePath}"
+newLibraryOutput="${newOutPath}/${m2repositoryRelativePath}/${newLibraryRelativePath}"
+
+echo unzipping aars
+find ${oldLibraryOutput} -name "*.aar" -exec sh -c 'unzip -o -d `dirname {}` {}' ';'
+find ${newLibraryOutput} -name "*.aar" -exec sh -c 'unzip -o -d `dirname {}` {}' ';'
+
+oldClasses="$(find ${oldLibraryOutput} -name "classes.jar")"
+newClasses="$(find ${newLibraryOutput} -name "classes.jar")"
+
+echo
+echo old classes.jar
+echo ${oldClasses}
+echo
+echo new classes.jar
+echo ${newClasses}
+echo
+echo example japi-compliance-checker command
+echo ./japi-compliance-checker.pl -lib ${newLibrary} ${oldClasses} ${newClasses}
+
+echo
+echo diffing .module file
+oldModuleFile="$(find ${oldLibraryOutput} -name "*.module")"
+newModuleFile="$(find ${newLibraryOutput} -name "*.module")"
+diff ${oldModuleFile} ${newModuleFile}
+
+echo
+echo diffing .pom file
+oldPomFile="$(find ${oldLibraryOutput} -name "*.pom")"
+newPomFile="$(find ${newLibraryOutput} -name "*.pom")"
+diff ${oldPomFile} ${newPomFile}
+
+echo
+echo diffing overall directory
+# Ignore checksums and classes.jar file
+diff -r -x "*.md5*" -x "*.sha*" -x "classes.jar" ${oldLibraryOutput} ${newLibraryOutput}
diff --git a/development/validateRefactor.sh b/development/validateRefactor.sh
index a12fa87..76d4f002 100755
--- a/development/validateRefactor.sh
+++ b/development/validateRefactor.sh
@@ -106,6 +106,12 @@
   done
 }
 function doBuild() {
+  # build compose
+  echoAndDo ./ui/gradlew -p ui createArchive generateDocs --no-daemon --rerun-tasks --offline
+  archiveName="top-of-tree-m2repository-all-0.zip"
+  echoAndDo unzip -q "${tempOutPath}/dist/ui/${archiveName}" -d "${tempOutPath}/dist/ui/${archiveName}.unzipped"
+
+  # build androidx
   echoAndDo ./gradlew createArchive generateDocs --no-daemon --rerun-tasks --offline
   archiveName="top-of-tree-m2repository-all-0.zip"
   echoAndDo unzip -q "${tempOutPath}/dist/${archiveName}" -d "${tempOutPath}/dist/${archiveName}.unzipped"
@@ -124,6 +130,7 @@
   usage
 fi
 newCommits="$(getCurrentCommits $projectPaths)"
+cd "$supportRoot"
 echo new commits: $newCommits
 
 oldOutPath="${checkoutRoot}/out-old"
@@ -155,5 +162,5 @@
 # Don't care about maven-metadata files because they have timestamps in them
 # We might care to know whether .sha1 or .md5 files have changed, but changes in those files will always be accompanied by more meaningful changes in other files, so we don't need to show changes in .sha1 or .md5 files
 # We also don't care about several specific files, either
-echoAndDo diff -r -x "*.md5*" -x "*.sha*" -x "*maven-metadata.xml" -x buildSrc.jar -x jetifier-standalone.zip -x jetpad-integration.jar -x "top-of-tree-m2repository-all-0.zip" -x noto-emoji-compat-java.jar -x versionedparcelable-annotation.jar -x dokkaTipOfTreeDocs-0.zip -x fakeannotations.jar -x "doclava*.jar" "$oldOutPath" "$newOutPath"
+echoAndDo diff -r -x "*.md5*" -x "*.sha*" -x "*maven-metadata.xml" -x buildSrc.jar -x jetifier-standalone.zip -x jetpad-integration.jar -x "top-of-tree-m2repository-all-0.zip" -x noto-emoji-compat-java.jar -x versionedparcelable-annotation.jar -x dokkaTipOfTreeDocs-0.zip -x fakeannotations.jar -x "doclava*.jar" "$oldOutPath/dist" "$newOutPath/dist"
 echo end of difference
diff --git a/docs-fake/build.gradle b/docs-fake/build.gradle
index 072278fb..35618cb 100644
--- a/docs-fake/build.gradle
+++ b/docs-fake/build.gradle
@@ -59,7 +59,6 @@
 android {
     defaultConfig {
         minSdkVersion SupportConfig.TARGET_SDK_VERSION
-        javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = false
     }
 
     sourceSets {
diff --git a/mediarouter/mediarouter/api/1.2.0-alpha02.txt b/mediarouter/mediarouter/api/1.2.0-alpha02.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/1.2.0-alpha02.txt
+++ b/mediarouter/mediarouter/api/1.2.0-alpha02.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/api/current.txt b/mediarouter/mediarouter/api/current.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/current.txt
+++ b/mediarouter/mediarouter/api/current.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/api/public_plus_experimental_1.2.0-alpha02.txt b/mediarouter/mediarouter/api/public_plus_experimental_1.2.0-alpha02.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/public_plus_experimental_1.2.0-alpha02.txt
+++ b/mediarouter/mediarouter/api/public_plus_experimental_1.2.0-alpha02.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/api/public_plus_experimental_current.txt b/mediarouter/mediarouter/api/public_plus_experimental_current.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/public_plus_experimental_current.txt
+++ b/mediarouter/mediarouter/api/public_plus_experimental_current.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/api/restricted_1.2.0-alpha02.txt b/mediarouter/mediarouter/api/restricted_1.2.0-alpha02.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/restricted_1.2.0-alpha02.txt
+++ b/mediarouter/mediarouter/api/restricted_1.2.0-alpha02.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/api/restricted_current.txt b/mediarouter/mediarouter/api/restricted_current.txt
index b5bd37a..bd8f8b9 100644
--- a/mediarouter/mediarouter/api/restricted_current.txt
+++ b/mediarouter/mediarouter/api/restricted_current.txt
@@ -3,7 +3,7 @@
 
   public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
     ctor public MediaRouteActionProvider(android.content.Context!);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
@@ -18,7 +18,7 @@
     ctor public MediaRouteButton(android.content.Context!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!);
     ctor public MediaRouteButton(android.content.Context!, android.util.AttributeSet!, int);
-    method public void enableDynamicGroup();
+    method @Deprecated public void enableDynamicGroup();
     method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
     method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
     method public void onAttachedToWindow();
@@ -366,7 +366,6 @@
     field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
     field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
     field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
-    field public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
     field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
     field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
     field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
@@ -447,11 +446,13 @@
 
   public class MediaRouterParams {
     ctor public MediaRouterParams();
+    ctor public MediaRouterParams(androidx.mediarouter.media.MediaRouterParams);
     method public int getDialogType();
+    method public boolean isOutputSwitcherEnabled();
     method public void setDialogType(int);
+    method public void setOutputSwitcherEnabled(boolean);
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
     field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
-    field public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3; // 0x3
   }
 
   public final class MediaSessionStatus {
@@ -476,6 +477,11 @@
     method public androidx.mediarouter.media.MediaSessionStatus.Builder! setTimestamp(long);
   }
 
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
   public class RemotePlaybackClient {
     ctor public RemotePlaybackClient(android.content.Context!, androidx.mediarouter.media.MediaRouter.RouteInfo!);
     method public void endSession(android.os.Bundle!, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback!);
diff --git a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
index ad7ddaf..a940b87 100644
--- a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
+++ b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
@@ -20,10 +20,12 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
+import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
@@ -41,106 +43,145 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class MediaRouterTest {
-   // The maximum time to wait for an operation.
-   private static final long TIME_OUT_MS = 3000L;
-   private static final String SESSION_TAG = "test-session";
-   private final Object mWaitLock = new Object();
+    // The maximum time to wait for an operation.
+    private static final long TIME_OUT_MS = 3000L;
+    private static final String SESSION_TAG = "test-session";
 
-   private Context mContext;
-   private MediaRouter mRouter;
-   private MediaSessionCompat mSession;
-   private MediaSessionCallback mSessionCallback = new MediaSessionCallback();
+    private static final String TEST_KEY = "test_key";
+    private static final String TEST_VALUE = "test_value";
 
-   @Before
-   public void setUp() throws Exception {
-       getInstrumentation().runOnMainSync(new Runnable() {
-           @Override
-           public void run() {
-               mContext = getApplicationContext();
-               mRouter = MediaRouter.getInstance(mContext);
-               mSession = new MediaSessionCompat(mContext, SESSION_TAG);
-           }
-       });
-   }
+    private final Object mWaitLock = new Object();
 
-   @After
-   public void tearDown() throws Exception {
-       mSession.release();
-   }
+    private Context mContext;
+    private MediaRouter mRouter;
+    private MediaSessionCompat mSession;
+    private MediaSessionCallback mSessionCallback = new MediaSessionCallback();
 
-   /**
-    * This test checks whether the session callback work properly after setMediaSessionCompat() is
-    * called.
-    */
-   @Test
-   @SmallTest
-   public void setMediaSessionCompat_receivesCallbacks() throws Exception {
-       getInstrumentation().runOnMainSync(new Runnable() {
-           @Override
-           public void run() {
-               mSession.setCallback(mSessionCallback);
-               mRouter.setMediaSessionCompat(mSession);
-           }
-       });
+    @Before
+    public void setUp() throws Exception {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mContext = getApplicationContext();
+                mRouter = MediaRouter.getInstance(mContext);
+                mSession = new MediaSessionCompat(mContext, SESSION_TAG);
+            }
+        });
+    }
 
-       MediaControllerCompat controller = mSession.getController();
-       MediaControllerCompat.TransportControls controls = controller.getTransportControls();
-       synchronized (mWaitLock) {
-           mSessionCallback.reset();
-           controls.play();
-           mWaitLock.wait(TIME_OUT_MS);
-           assertTrue(mSessionCallback.mOnPlayCalled);
+    @After
+    public void tearDown() throws Exception {
+        mSession.release();
+    }
 
-           mSessionCallback.reset();
-           controls.pause();
-           mWaitLock.wait(TIME_OUT_MS);
-           assertTrue(mSessionCallback.mOnPauseCalled);
-       }
-   }
+    /**
+     * This test checks whether the session callback work properly after setMediaSessionCompat() is
+     * called.
+     */
+    @Test
+    @SmallTest
+    public void setMediaSessionCompat_receivesCallbacks() throws Exception {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mSession.setCallback(mSessionCallback);
+                mRouter.setMediaSessionCompat(mSession);
+            }
+        });
+
+        MediaControllerCompat controller = mSession.getController();
+        MediaControllerCompat.TransportControls controls = controller.getTransportControls();
+        synchronized (mWaitLock) {
+            mSessionCallback.reset();
+            controls.play();
+            mWaitLock.wait(TIME_OUT_MS);
+            assertTrue(mSessionCallback.mOnPlayCalled);
+
+            mSessionCallback.reset();
+            controls.pause();
+            mWaitLock.wait(TIME_OUT_MS);
+            assertTrue(mSessionCallback.mOnPauseCalled);
+        }
+    }
 
     @Test
     @SmallTest
-    public void getRouteParams_afterSetRouterParams_returnsSetParams() {
+    public void getRouterParams_afterSetRouterParams_returnsSetParams() {
         MediaRouterParams expectedParams = new MediaRouterParams();
         expectedParams.setDialogType(MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP);
+
+        final boolean isOutputSwitcherEnabled = true;
+        expectedParams.setOutputSwitcherEnabled(isOutputSwitcherEnabled);
+
         Bundle paramExtras = new Bundle();
-        paramExtras.putString("test_key", "test_value");
+        paramExtras.putString(TEST_KEY, TEST_VALUE);
         expectedParams.setExtras(paramExtras);
-        paramExtras.remove("test_key");
+        paramExtras.remove(TEST_KEY);
         mRouter.setRouterParams(expectedParams);
 
         MediaRouterParams actualParams = mRouter.getRouterParams();
         assertNotNull(actualParams);
         assertEquals(expectedParams.getDialogType(), actualParams.getDialogType());
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            assertEquals(isOutputSwitcherEnabled, expectedParams.isOutputSwitcherEnabled());
+            assertEquals(isOutputSwitcherEnabled, actualParams.isOutputSwitcherEnabled());
+        } else {
+            // Earlier than Android R, output switcher cannot be enabled.
+            assertFalse(expectedParams.isOutputSwitcherEnabled());
+            assertFalse(actualParams.isOutputSwitcherEnabled());
+        }
+
         Bundle actualExtras = actualParams.getExtras();
         assertNotNull(actualExtras);
-        assertEquals("test_value", actualExtras.getString("test_key"));
+        assertEquals(TEST_VALUE, actualExtras.getString(TEST_KEY));
     }
 
-   private class MediaSessionCallback extends MediaSessionCompat.Callback {
-       private boolean mOnPlayCalled;
-       private boolean mOnPauseCalled;
+    @Test
+    @SmallTest
+    public void copyConstructorOfMediaRouterParams() {
+        MediaRouterParams originalParams = new MediaRouterParams();
+        originalParams.setDialogType(MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP);
+        originalParams.setOutputSwitcherEnabled(true);
 
-       public void reset() {
-           mOnPlayCalled = false;
-           mOnPauseCalled = false;
-       }
+        Bundle paramExtras = new Bundle();
+        paramExtras.putString(TEST_KEY, TEST_VALUE);
+        originalParams.setExtras(paramExtras);
 
-       @Override
-       public void onPlay() {
-           synchronized (mWaitLock) {
-               mOnPlayCalled = true;
-               mWaitLock.notify();
-           }
-       }
+        // Test the copy constructor
+        MediaRouterParams copiedParams = new MediaRouterParams(originalParams);
+        assertEquals(originalParams.getDialogType(), copiedParams.getDialogType());
+        assertEquals(originalParams.isOutputSwitcherEnabled(),
+                copiedParams.isOutputSwitcherEnabled());
 
-       @Override
-       public void onPause() {
-           synchronized (mWaitLock) {
-               mOnPauseCalled = true;
-               mWaitLock.notify();
-           }
-       }
-   }
+        Bundle copiedParamsExtras = copiedParams.getExtras();
+        assertNotNull(copiedParamsExtras);
+        assertEquals(TEST_VALUE, copiedParamsExtras.getString(TEST_KEY));
+    }
+
+    private class MediaSessionCallback extends MediaSessionCompat.Callback {
+        private boolean mOnPlayCalled;
+        private boolean mOnPauseCalled;
+
+        public void reset() {
+            mOnPlayCalled = false;
+            mOnPauseCalled = false;
+        }
+
+        @Override
+        public void onPlay() {
+            synchronized (mWaitLock) {
+                mOnPlayCalled = true;
+                mWaitLock.notify();
+            }
+        }
+
+        @Override
+        public void onPause() {
+            synchronized (mWaitLock) {
+                mOnPauseCalled = true;
+                mWaitLock.notify();
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteActionProvider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteActionProvider.java
index 33e327e..e8e04cf 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteActionProvider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteActionProvider.java
@@ -28,6 +28,7 @@
 import androidx.core.view.ActionProvider;
 import androidx.mediarouter.media.MediaRouteSelector;
 import androidx.mediarouter.media.MediaRouter;
+import androidx.mediarouter.media.MediaRouterParams;
 
 import java.lang.ref.WeakReference;
 
@@ -138,7 +139,6 @@
     private MediaRouteSelector mSelector = MediaRouteSelector.EMPTY;
     private MediaRouteDialogFactory mDialogFactory = MediaRouteDialogFactory.getDefault();
     private MediaRouteButton mButton;
-    private boolean mUseDynamicGroup;
     private boolean mAlwaysVisible;
 
     /**
@@ -207,12 +207,17 @@
      *
      * @see MediaRouteButton#enableDynamicGroup()
      * @see androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController
+     *
+     * @deprecated Use {@link androidx.mediarouter.media.MediaRouterParams#setDialogType(int)}
+     * with {@link androidx.mediarouter.media.MediaRouterParams#DIALOG_TYPE_DYNAMIC_GROUP} instead.
      */
+    @Deprecated
     public void enableDynamicGroup() {
-        mUseDynamicGroup = true;
-        if (mButton != null) {
-            mButton.enableDynamicGroup();
-        }
+        MediaRouterParams oldParams = mRouter.getRouterParams();
+        MediaRouterParams newParams = oldParams == null ? new MediaRouterParams() :
+                new MediaRouterParams(oldParams);
+        newParams.setDialogType(MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP);
+        mRouter.setRouterParams(newParams);
     }
 
     /**
@@ -295,9 +300,6 @@
         mButton = onCreateMediaRouteButton();
         mButton.setCheatSheetEnabled(true);
         mButton.setRouteSelector(mSelector);
-        if (mUseDynamicGroup) {
-            mButton.enableDynamicGroup();
-        }
         mButton.setAlwaysVisible(mAlwaysVisible);
         mButton.setDialogFactory(mDialogFactory);
         mButton.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
index ea4c9ea..90e894e 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteButton.java
@@ -49,6 +49,7 @@
 import androidx.mediarouter.R;
 import androidx.mediarouter.media.MediaRouteSelector;
 import androidx.mediarouter.media.MediaRouter;
+import androidx.mediarouter.media.MediaRouterParams;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -92,8 +93,6 @@
 public class MediaRouteButton extends View {
     private static final String TAG = "MediaRouteButton";
 
-    private static final boolean USE_OUTPUT_SWITCHER_IF_AVAILABLE = true;
-
     private static final String CHOOSER_FRAGMENT_TAG =
             "android.support.v7.mediarouter:MediaRouteChooserDialogFragment";
     private static final String CONTROLLER_FRAGMENT_TAG =
@@ -131,7 +130,6 @@
     private int mMinWidth;
     private int mMinHeight;
 
-    private boolean mUseDynamicGroup;
     private boolean mAlwaysVisible;
     private boolean mCheatSheetEnabled;
 
@@ -283,9 +281,17 @@
      * supports dynamic group, the users can use that feature with the dialogs.
      *
      * @see androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController
+     *
+     * @deprecated Use {@link androidx.mediarouter.media.MediaRouterParams#setDialogType(int)}
+     * with {@link androidx.mediarouter.media.MediaRouterParams#DIALOG_TYPE_DYNAMIC_GROUP} instead.
      */
+    @Deprecated
     public void enableDynamicGroup() {
-        mUseDynamicGroup = true;
+        MediaRouterParams oldParams = mRouter.getRouterParams();
+        MediaRouterParams newParams = oldParams == null ? new MediaRouterParams() :
+                new MediaRouterParams(oldParams);
+        newParams.setDialogType(MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP);
+        mRouter.setRouterParams(newParams);
     }
 
     /**
@@ -296,54 +302,51 @@
      * Otherwise, shows the route controller dialog to offer the user
      * a choice to disconnect from the route or perform other control actions
      * such as setting the route's volume.
-     * </p><p>
+     * <p>
+     * Dialog types can be set by setting {@link MediaRouterParams} to the router.
+     * <p>
      * The application can customize the dialogs by calling {@link #setDialogFactory}
      * to provide a customized dialog factory.
-     * </p>
+     * <p>
      *
      * @return True if the dialog was actually shown.
      *
      * @throws IllegalStateException if the activity is not a subclass of
      * {@link FragmentActivity}.
+     *
+     * @see MediaRouterParams#setDialogType(int)
+     * @see MediaRouterParams#setOutputSwitcherEnabled(boolean)
      */
     public boolean showDialog() {
         if (!mAttachedToWindow) {
             return false;
         }
 
-        if (USE_OUTPUT_SWITCHER_IF_AVAILABLE && MediaRouter.isTransferEnabled()) {
-            Context context = getContext();
-
-            Intent intent = new Intent()
-                    .setAction(OutputSwitcherConstants.ACTION_MEDIA_OUTPUT)
-                    .putExtra(OutputSwitcherConstants.EXTRA_PACKAGE_NAME, context.getPackageName())
-                    .putExtra(OutputSwitcherConstants.KEY_MEDIA_SESSION_TOKEN,
-                            mRouter.getMediaSessionToken());
-
-            PackageManager packageManager = context.getPackageManager();
-            List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
-            for (ResolveInfo resolveInfo : resolveInfos) {
-                ActivityInfo activityInfo = resolveInfo.activityInfo;
-                if (activityInfo == null || activityInfo.applicationInfo == null) {
-                    continue;
-                }
-                ApplicationInfo appInfo = activityInfo.applicationInfo;
-                if (((ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)
-                        & appInfo.flags) != 0) {
-                    context.startActivity(intent);
+        MediaRouterParams params = mRouter.getRouterParams();
+        if (params != null) {
+            if (params.isOutputSwitcherEnabled() && MediaRouter.isMediaTransferEnabled()) {
+                if (showOutputSwitcher()) {
+                    // Output switcher is successfully shown.
                     return true;
                 }
             }
-            // If there is no output switcher, fall back to the normal dialog.
+            int dialogType = params.getDialogType();
+            return showDialogForType(dialogType);
+        } else {
+            // Note: These apps didn't call enableDynamicGroup(), since calling the method
+            // automatically sets a MediaRouterParams with dynamic dialog type.
+            return showDialogForType(MediaRouterParams.DIALOG_TYPE_DEFAULT);
         }
+    }
 
+    private boolean showDialogForType(@MediaRouterParams.DialogType int dialogType) {
         final FragmentManager fm = getFragmentManager();
         if (fm == null) {
             throw new IllegalStateException("The activity must be a subclass of FragmentActivity");
         }
+        MediaRouter.RouteInfo selectedRoute = mRouter.getSelectedRoute();
 
-        MediaRouter.RouteInfo route = mRouter.getSelectedRoute();
-        if (route.isDefaultOrBluetooth() || !route.matchesSelector(mSelector)) {
+        if (selectedRoute.isDefaultOrBluetooth() || !selectedRoute.matchesSelector(mSelector)) {
             if (fm.findFragmentByTag(CHOOSER_FRAGMENT_TAG) != null) {
                 Log.w(TAG, "showDialog(): Route chooser dialog already showing!");
                 return false;
@@ -351,7 +354,10 @@
             MediaRouteChooserDialogFragment f =
                     mDialogFactory.onCreateChooserDialogFragment();
             f.setRouteSelector(mSelector);
-            f.setUseDynamicGroup(mUseDynamicGroup);
+
+            if (dialogType == MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP) {
+                f.setUseDynamicGroup(true);
+            }
 
             FragmentTransaction transaction = fm.beginTransaction();
             transaction.add(f, CHOOSER_FRAGMENT_TAG);
@@ -364,7 +370,10 @@
             MediaRouteControllerDialogFragment f =
                     mDialogFactory.onCreateControllerDialogFragment();
             f.setRouteSelector(mSelector);
-            f.setUseDynamicGroup(mUseDynamicGroup);
+
+            if (dialogType == MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP) {
+                f.setUseDynamicGroup(true);
+            }
 
             FragmentTransaction transaction = fm.beginTransaction();
             transaction.add(f, CONTROLLER_FRAGMENT_TAG);
@@ -373,6 +382,37 @@
         return true;
     }
 
+    /**
+     * Shows output switcher dialog. Returns {@code true} if it is successfully shown.
+     * Returns {@code false} if there was no output switcher.
+     */
+    private boolean showOutputSwitcher() {
+        Context context = getContext();
+
+        Intent intent = new Intent()
+                .setAction(OutputSwitcherConstants.ACTION_MEDIA_OUTPUT)
+                .putExtra(OutputSwitcherConstants.EXTRA_PACKAGE_NAME, context.getPackageName())
+                .putExtra(OutputSwitcherConstants.KEY_MEDIA_SESSION_TOKEN,
+                        mRouter.getMediaSessionToken());
+
+        PackageManager packageManager = context.getPackageManager();
+        List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null || activityInfo.applicationInfo == null) {
+                continue;
+            }
+            ApplicationInfo appInfo = activityInfo.applicationInfo;
+            if (((ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)
+                    & appInfo.flags) != 0) {
+                context.startActivity(intent);
+                return true;
+            }
+        }
+        // There was no output switcher.
+        return false;
+    }
+
     private FragmentManager getFragmentManager() {
         Activity activity = getActivity();
         if (activity instanceof FragmentActivity) {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
index 87823b6..44683b4 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
@@ -59,7 +59,7 @@
 
 /**
  * Provides routes and RouteController by using MediaRouter2.
- * This provider is added only when seamless transfer feature is enabled.
+ * This provider is added only when media transfer feature is enabled.
  */
 @RequiresApi(Build.VERSION_CODES.R)
 @SuppressWarnings({"unused", "ClassCanBeStatic"}) // TODO: Remove this.
@@ -221,7 +221,7 @@
     void setDynamicRouteDescriptors(MediaRouter2.RoutingController routingController) {
         GroupRouteController controller = mControllerMap.get(routingController);
         if (controller == null) {
-            Log.w(TAG, "onControllerUpdated: No matching routeController found. "
+            Log.w(TAG, "setDynamicRouteDescriptors: No matching routeController found. "
                     + "routingController=" + routingController);
             return;
         }
@@ -265,7 +265,7 @@
 
         MediaRouteProviderDescriptor providerDescriptor = getDescriptor();
         if (providerDescriptor == null) {
-            Log.w(TAG, "onControllerUpdated: providerDescriptor is not set.");
+            Log.w(TAG, "setDynamicRouteDescriptors: providerDescriptor is not set.");
             return;
         }
 
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderProtocol.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderProtocol.java
index 091bf5d..5aa2914 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderProtocol.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderProtocol.java
@@ -259,7 +259,7 @@
 
     /**
      * The client version used from androidx 1.2.0.
-     * Seamless transfer feature is added in this version.
+     * Media transfer feature is added in this version.
      */
     public static final int CLIENT_VERSION_4 = 4;
 
@@ -285,7 +285,7 @@
 
     /**
      * The service version used from androidx 1.2.0.
-     * Seamless transfer feature is added in this version.
+     * Media transfer feature is added in this version.
      */
     public static final int SERVICE_VERSION_3 = 3;
 
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index 6becf8c..c935819 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -26,8 +26,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -83,33 +81,6 @@
  * to ask the route's destination to perform certain remote control functions
  * such as playing media.
  * </p><p>
- * Features of MediaRouter can be enabled by adding a
- * <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a> element
- * as a child of the <code>&lt;application&gt;</code> element. Set the
- * <code>&lt;meta-data&gt;</code> element's "android:name" attribute to
- * {@link #METADATA_NAME_FEATURE "androidx.mediarouter.FEATURE"}, and set the
- * "android:value" attribute as one of the followings:
- * <ol>
- *     <li><code>default</code>: Basic route selection and controls.</li>
- *     <li><code>dynamic_group</code>: Grouping/Ungrouping multiple routes can be done while
- *          routing. Also, the default implementation of
- *          {@link androidx.mediarouter.app.MediaRouteButton} will show the different dialogs
- *          appropriate for adding/removing routes from a group. This constant includes the
- *          <code>default</code> feature above.</li>
- *     <li><code>seamless_transfer</code>: Routes selection/controls can be done via System UI.
- *          Also, the transfer of media can be done seamlessly. Enabling this feature will make the
- *          users be able to control the routing even outside of your app's activity.
- *          Includes the <code>dynamic_group</code> feature above.</li>
- * </ol>
- * For example:
- * <pre class="prettyprint">{@code
- * <application>
- *     <meta-data
- *          android:name="androidx.mediarouter.FEATURE"
- *          android:value="seamless_transfer" />
- * </activity>
- * }</pre>
- * </p><p>
  * See also {@link MediaRouteProvider} for information on how an application
  * can publish new media routes to the media router.
  * </p><p>
@@ -117,19 +88,11 @@
  * done from the main thread of the process.
  * </p>
  */
-// TODO: Refer {@link Callback#onPrepareTransfer()} in seamless_transfer when the API is ready.
 // TODO: Add the javadoc for manifest requirements about 'Package visibility' in Android 11
 public final class MediaRouter {
     static final String TAG = "MediaRouter";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    /**
-     * The name of the meta-data element for specifying media router feature.
-     */
-    public static final String METADATA_NAME_FEATURE = "androidx.mediarouter.FEATURE";
-    static final String METADATA_FEATURE_DYNAMIC_GROUP = "dynamic_group";
-    static final String METADATA_FEATURE_SEAMLESS_TRANSFER = "seamless_transfer";
-
     @IntDef({UNSELECT_REASON_UNKNOWN, UNSELECT_REASON_DISCONNECTED, UNSELECT_REASON_STOPPED,
             UNSELECT_REASON_ROUTE_CHANGED})
     @Retention(RetentionPolicy.SOURCE)
@@ -902,17 +865,17 @@
     }
 
     /**
-     * Returns whether the seamless transfer feature is enabled.
+     * Returns whether the media transfer feature is enabled.
      *
      * @see MediaRouter
      * @hide
      */
     @RestrictTo(LIBRARY)
-    public static boolean isTransferEnabled() {
+    public static boolean isMediaTransferEnabled() {
         if (sGlobal == null) {
             return false;
         }
-        return sGlobal.isTransferEnabled();
+        return sGlobal.isMediaTransferEnabled();
     }
 
     /**
@@ -2242,8 +2205,7 @@
             implements SystemMediaRouteProvider.SyncCallback,
             RegisteredMediaRouteProviderWatcher.Callback {
         final Context mApplicationContext;
-        final boolean mDynamicGroupEnabled;
-        final boolean mTransferEnabled;
+        final boolean mMediaTransferEnabled;
         final MediaRoute2Provider mMr2Provider;
         final ArrayList<WeakReference<MediaRouter>> mRouters = new ArrayList<>();
         private final ArrayList<RouteInfo> mRoutes = new ArrayList<>();
@@ -2295,29 +2257,13 @@
                     (ActivityManager)applicationContext.getSystemService(
                             Context.ACTIVITY_SERVICE));
 
-            String feature = null;
-            try {
-                int flags = PackageManager.GET_META_DATA;
-                ApplicationInfo appInfo = applicationContext.getPackageManager()
-                        .getApplicationInfo(applicationContext.getPackageName(), flags);
-                feature = appInfo.metaData.getString(METADATA_NAME_FEATURE);
-            } catch (Exception ex) {
-                Log.w(TAG, "GlobalMediaRouter: Exception while getting feature.", ex);
-            }
-
-            if (TextUtils.equals(feature, METADATA_FEATURE_SEAMLESS_TRANSFER)) {
-                mDynamicGroupEnabled = true;
-                mTransferEnabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
-            } else if (TextUtils.equals(feature, METADATA_FEATURE_DYNAMIC_GROUP)) {
-                mDynamicGroupEnabled = true;
-                mTransferEnabled = false;
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+                mMediaTransferEnabled = MediaTransferReceiver.isDeclared(mApplicationContext);
             } else {
-                // Note: Includes 'default'
-                mDynamicGroupEnabled = false;
-                mTransferEnabled = false;
+                mMediaTransferEnabled = false;
             }
 
-            if (mTransferEnabled) {
+            if (mMediaTransferEnabled) {
                 mMr2Provider = new MediaRoute2Provider(
                         mApplicationContext, new Mr2ProviderCallback());
             } else {
@@ -2633,15 +2579,8 @@
             return mCallbackCount;
         }
 
-        // TODO: Branch code by using this method.
-        //       (e.g. Show the dynamic controller dialog only when this method returns true).
-        // TODO: Create MediaRouter#isDynamicGroupEnabled() (static method) if needed.
-        boolean isDynamicGroupEnabled() {
-            return mDynamicGroupEnabled;
-        }
-
-        boolean isTransferEnabled() {
-            return mTransferEnabled;
+        boolean isMediaTransferEnabled() {
+            return mMediaTransferEnabled;
         }
 
         @Override
@@ -3224,7 +3163,8 @@
                 mPlaybackInfo.volumeHandling = mSelectedRoute.getVolumeHandling();
                 mPlaybackInfo.playbackStream = mSelectedRoute.getPlaybackStream();
                 mPlaybackInfo.playbackType = mSelectedRoute.getPlaybackType();
-                if (mTransferEnabled && mSelectedRoute.getProviderInstance() == mMr2Provider) {
+                if (mMediaTransferEnabled
+                        && mSelectedRoute.getProviderInstance() == mMr2Provider) {
                     mPlaybackInfo.volumeControlId = MediaRoute2Provider
                             .getSessionIdForRouteController(mSelectedRouteController);
                 } else {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
index 5459168..7d292c9 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
@@ -18,6 +18,7 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 
+import android.os.Build;
 import android.os.Bundle;
 
 import androidx.annotation.IntDef;
@@ -47,19 +48,10 @@
     public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2;
 
     /**
-     * A dialog type that shows the Output Switcher.
-     * Use this dialog type to provide consistent casting UX with Android framework.
-     * <p>
-     * On devices that do not support API level 30 or higher, {@link #DIALOG_TYPE_DEFAULT) would
-     * be used.
-     */
-    public static final int DIALOG_TYPE_OUTPUT_SWITCHER = 3;
-
-    /**
      * @hide
      */
     @RestrictTo(LIBRARY)
-    @IntDef({DIALOG_TYPE_DEFAULT, DIALOG_TYPE_DYNAMIC_GROUP, DIALOG_TYPE_OUTPUT_SWITCHER})
+    @IntDef({DIALOG_TYPE_DEFAULT, DIALOG_TYPE_DYNAMIC_GROUP})
     @Retention(RetentionPolicy.SOURCE)
     public @interface DialogType {}
 
@@ -71,6 +63,7 @@
             "androidx.mediarouter.media.MediaRouterParams.TEST_PRIVATE_UI";
 
     private int mDialogType = DIALOG_TYPE_DEFAULT;
+    private boolean mOutputSwitcherEnabled = false;
     private Bundle mExtras = Bundle.EMPTY;
 
     /**
@@ -80,7 +73,21 @@
     }
 
     /**
-     * Gets the media route controller dialog type.
+     * A copy constructor for MediaRouterParams.
+     */
+    public MediaRouterParams(@NonNull MediaRouterParams params) {
+        if (params == null) {
+            throw new NullPointerException("params should not be null!");
+        }
+
+        mDialogType = params.mDialogType;
+        mOutputSwitcherEnabled = params.mOutputSwitcherEnabled;
+        mExtras = params.mExtras == null ? Bundle.EMPTY : new Bundle(params.mExtras);
+    }
+
+    /**
+     * Gets the media route controller dialog type. Default value is {@link #DIALOG_TYPE_DEFAULT}
+     * if not set.
      */
     public @DialogType int getDialogType() {
         return mDialogType;
@@ -88,14 +95,52 @@
 
     /**
      * Sets the media route controller dialog type.
+     * <p>
+     * Note that from Android R, output switcher will be used rather than the dialog type set by
+     * this method if both {@link #setOutputSwitcherEnabled(boolean) output switcher} and
+     * {@link MediaTransferReceiver media transfer feature} are enabled.
      *
-     * @param dialogType
+     * @param dialogType the dialog type
+     * @see #setOutputSwitcherEnabled(boolean)
+     * @see #DIALOG_TYPE_DEFAULT
+     * @see #DIALOG_TYPE_DYNAMIC_GROUP
      */
     public void setDialogType(@DialogType int dialogType) {
         mDialogType = dialogType;
     }
 
     /**
+     * Sets whether output switcher dialogs are enabled. This method will be no-op for Android
+     * versions earlier than Android R.
+     * <p>
+     * If set to {@code true}, and when {@link MediaTransferReceiver media transfer is enabled},
+     * {@link androidx.mediarouter.app.MediaRouteButton MediaRouteButton} will show output
+     * switcher when clicked, no matter what type of dialog is set by {@link #setDialogType(int)}.
+     * <p>
+     * If set to {@code false}, {@link androidx.mediarouter.app.MediaRouteButton MediaRouteButton}
+     * will show the dialog type which is set by {@link #setDialogType(int)}.
+     *
+     * @see #isOutputSwitcherEnabled()
+     */
+    public void setOutputSwitcherEnabled(boolean enabled) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            mOutputSwitcherEnabled = enabled;
+        }
+    }
+
+    /**
+     * Gets whether the output switcher dialog is enabled. Default value is {@code false} if not
+     * set.
+     * <p>
+     * Note that it always returns {@code false} for Android versions earlier than Android R.
+     *
+     * @see #setOutputSwitcherEnabled(boolean)
+     */
+    public boolean isOutputSwitcherEnabled() {
+        return mOutputSwitcherEnabled;
+    }
+
+    /**
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaTransferReceiver.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaTransferReceiver.java
new file mode 100644
index 0000000..7e8969a
--- /dev/null
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaTransferReceiver.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 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 androidx.mediarouter.media;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+
+import java.util.List;
+
+/**
+ * A {@link BroadcastReceiver} class for enabling Media transfer feature.
+ * <p>
+ * Media transfer is a feature that media routing can be controlled via system UI. By using this,
+ * media app users can re-route the media without opening the app activity again. Also, the media
+ * can be transferred from one device to another device seamlessly, depending on the devices.
+ * This feature is supported from Android 11.
+ * <p>
+ * To enable the media transfer feature, media apps should declare this receiver in the app's
+ * manifest. For example:
+ * <pre class="prettyprint">{@code
+ * <application>
+ *     <receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
+ * </application>
+ * }</pre>
+ * <p>
+ * Media apps that enable this feature should implement the {@link MediaRouter.Callback} properly.
+ * Specifically:
+ * <ul>
+ *     <li>Apps should be able to get events even when the app is in background. This means
+ *         that the callback should not be removed in {@link Activity#onStop()}. (See
+ *         {@link MediaRouter#addCallback(MediaRouteSelector, MediaRouter.Callback, int)} for
+ *         how to add callback.</li>
+ *     <li>Apps should handle the case where the media routing is changed from the outside of the
+ *         app. The callback's
+ *         {@link MediaRouter.Callback#onRouteSelected(MediaRouter, MediaRouter.RouteInfo, int)
+ *         onRouteSelected} method should be able to handle the cases.</li>
+ * </ul>
+ */
+// TODO: Mention that devs should implement onPrepareTransfer() - after the API is ready.
+// TODO: For the C2P case, refer PARAM_CAST_TO_PHONE when the API is ready.
+public final class MediaTransferReceiver extends BroadcastReceiver  {
+    @Override
+    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
+        // Do nothing for now.
+    }
+
+    /**
+     * Check whether the {@link MediaTransferReceiver} is declared in the app manifest.
+     * @hide
+     */
+    @RestrictTo(LIBRARY)
+    public static boolean isDeclared(@NonNull Context applicationContext) {
+        Intent queryIntent = new Intent(applicationContext, MediaTransferReceiver.class);
+        queryIntent.setPackage(applicationContext.getPackageName());
+        PackageManager pm = applicationContext.getPackageManager();
+        List<ResolveInfo> resolveInfos = pm.queryBroadcastReceivers(queryIntent, 0);
+
+        return resolveInfos.size() > 0;
+    }
+}
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RegisteredMediaRouteProviderWatcher.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RegisteredMediaRouteProviderWatcher.java
index 45117e2..ab121f4 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RegisteredMediaRouteProviderWatcher.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RegisteredMediaRouteProviderWatcher.java
@@ -111,7 +111,7 @@
             if (serviceInfo == null) {
                 continue;
             }
-            if (MediaRouter.isTransferEnabled()
+            if (MediaRouter.isMediaTransferEnabled()
                     && listContainsServiceInfo(mediaRoute2ProviderServices, serviceInfo)) {
                 // Do not register services which supports MediaRoute2ProviderService,
                 // since we will communicate with them via MediaRouter2.
diff --git a/paging/common/api/api_lint.ignore b/paging/common/api/api_lint.ignore
index 806e977..7231489 100644
--- a/paging/common/api/api_lint.ignore
+++ b/paging/common/api/api_lint.ignore
@@ -1,9 +1,3 @@
 // Baseline format: 1.0
 AutoBoxing: androidx.paging.PagingState#getAnchorPosition():
     Must avoid boxed primitives (`java.lang.Integer`)
-
-
-MissingJvmstatic: androidx.paging.PagedListConfigKt#Config(int, int, boolean, int, int):
-    A Kotlin method with default parameter values should be annotated with @JvmOverloads for better Java interoperability; see https://android.github.io/kotlin-guides/interop.html#function-overloads-for-defaults
-MissingJvmstatic: androidx.paging.PagedListKt#PagedList(androidx.paging.DataSource<Key,Value>, androidx.paging.PagedList.Config, java.util.concurrent.Executor, java.util.concurrent.Executor, androidx.paging.PagedList.BoundaryCallback<Value>, Key):
-    A Kotlin method with default parameter values should be annotated with @JvmOverloads for better Java interoperability; see https://android.github.io/kotlin-guides/interop.html#function-overloads-for-defaults
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
index 2f89d21..5bd1633 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
@@ -1249,7 +1249,11 @@
  * @param boundaryCallback [PagedList.BoundaryCallback] for listening to out-of-data events.
  * @param initialKey [Key] the [DataSource] should load around as part of initialization.
  */
-@Suppress("FunctionName", "DEPRECATION")
+@Suppress(
+    "MissingJvmstatic", // Separate Java API
+    "FunctionName",
+    "DEPRECATION"
+)
 @Deprecated("DataSource is deprecated and has been replaced by PagingSource")
 fun <Key : Any, Value : Any> PagedList(
     dataSource: DataSource<Key, Value>,
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedListConfig.kt b/paging/common/src/main/kotlin/androidx/paging/PagedListConfig.kt
index c58704b..e41a9a2 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedListConfig.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedListConfig.kt
@@ -26,7 +26,11 @@
  * @param maxSize Maximum number of items to keep in memory, or
  * [PagedList.Config.MAX_SIZE_UNBOUNDED] to disable page dropping.
  */
-@Suppress("FunctionName", "DEPRECATION")
+@Suppress(
+    "MissingJvmstatic", // Separate Java API
+    "FunctionName",
+    "DEPRECATION"
+)
 fun Config(
     pageSize: Int,
     prefetchDistance: Int = pageSize,
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
index 20c9cee..5123892 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/element_ext.kt
@@ -22,6 +22,7 @@
 import com.google.auto.common.AnnotationMirrors
 import com.google.auto.common.MoreElements
 import com.google.auto.common.MoreTypes
+import isAssignableFrom
 import java.lang.reflect.Proxy
 import javax.annotation.processing.ProcessingEnvironment
 import javax.lang.model.element.AnnotationMirror
@@ -301,8 +302,13 @@
 }
 
 // a variant of Types.isAssignable that ignores variance.
-fun Types.isAssignableWithoutVariance(from: TypeMirror, to: TypeMirror): Boolean {
-    val assignable = isAssignable(from, to)
+fun TypeMirror.isAssignableFromWithoutVariance(
+    typeUtils: Types,
+    from: TypeMirror
+) = typeUtils.isAssignableWithoutVariance(from = from, to = this)
+
+private fun Types.isAssignableWithoutVariance(from: TypeMirror, to: TypeMirror): Boolean {
+    val assignable = to.isAssignableFrom(this, from)
     if (assignable) {
         return true
     }
@@ -318,7 +324,7 @@
         return false
     }
     // check erasure version first, if it does not match, no reason to proceed
-    if (!isAssignable(erasure(from), erasure(to))) {
+    if (!erasure(to).isAssignableFrom(this, erasure(from))) {
         return false
     }
     // convert from args to their upper bounds if it exists
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt
new file mode 100644
index 0000000..101bdcd
--- /dev/null
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/processing_env_ext.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2020 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 androidx.room.ext
+
+import com.squareup.javapoet.TypeName
+import javax.annotation.processing.ProcessingEnvironment
+import javax.lang.model.element.TypeElement
+import javax.lang.model.type.TypeMirror
+import kotlin.reflect.KClass
+
+/**
+ * Query a type element by KClass and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeElement(
+    klass: KClass<*>
+): TypeElement? = findTypeElement(klass.java.canonicalName!!)
+
+/**
+ * Query a type element by TypeName and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeElement(
+    typeName: TypeName
+): TypeElement? = findTypeElement(typeName.toString())
+
+/**
+ * Query a type element by qualified name and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeElement(
+    qName: String
+): TypeElement? = elementUtils.getTypeElement(qName)
+
+/**
+ * Query a type element by KClass and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeElement(
+    klass: KClass<*>
+): TypeElement = requireTypeElement(klass.java.canonicalName!!)
+
+/**
+ * Query a type element by TypeName and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeElement(
+    typeName: TypeName
+): TypeElement = requireTypeElement(typeName.toString())
+
+/**
+ * Query a type element by qualified name and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeElement(
+    qName: String
+): TypeElement = checkNotNull(elementUtils.getTypeElement(qName)) {
+    // we do not throw MissingTypeException here as this should be called only if the type should
+    // be there
+    "Couldn't find required type $qName"
+}
+
+/**
+ * Query a TypeMirror by KClass and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeMirror(
+    klass: KClass<*>
+): TypeMirror = requireTypeMirror(klass.java.canonicalName!!)
+
+/**
+ * Query a TypeMirror by TypeName and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeMirror(
+    typeName: TypeName
+): TypeMirror = requireTypeMirror(typeName.toString())
+
+/**
+ * Query a TypeMirror by qualified name and throw if it does not exist
+ */
+fun ProcessingEnvironment.requireTypeMirror(
+    qName: String
+): TypeMirror = requireTypeElement(qName).asType()
+
+/**
+ * Query a type mirror by KClass and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeMirror(
+    klass: KClass<*>
+): TypeMirror? = findTypeMirror(klass.java.canonicalName!!)
+
+/**
+ * Query a type mirror by TypeName and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeMirror(
+    typeName: TypeName
+): TypeMirror? = findTypeMirror(typeName.toString())
+
+/**
+ * Query a type mirror by qualified name and return null if it does not exist
+ */
+fun ProcessingEnvironment.findTypeMirror(
+    qName: String
+): TypeMirror? = findTypeElement(qName)?.asType()
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
index 5b5667c..f06a4bc 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/type_mirror_ext.kt
@@ -25,6 +25,7 @@
 import javax.lang.model.type.TypeKind.LONG
 import javax.lang.model.type.TypeKind.SHORT
 import javax.lang.model.type.TypeMirror
+import javax.lang.model.util.Types
 
 fun TypeMirror.defaultValue(): String {
     return when (this.kind) {
@@ -59,4 +60,8 @@
     MoreTypes.isType(this) && MoreTypes.isTypeOf(Void::class.java, this)
 
 fun TypeMirror.isKotlinUnit() =
-    MoreTypes.isType(this) && MoreTypes.isTypeOf(Unit::class.java, this)
\ No newline at end of file
+    MoreTypes.isType(this) && MoreTypes.isTypeOf(Unit::class.java, this)
+
+fun TypeMirror.isAssignableFrom(typeUtils: Types, other: TypeMirror): Boolean {
+    return typeUtils.isAssignable(other, this)
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
index 8a2d160..4d817c7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
@@ -17,6 +17,7 @@
 package androidx.room.parser
 
 import androidx.room.ColumnInfo
+import androidx.room.ext.requireTypeMirror
 import org.antlr.v4.runtime.tree.ParseTree
 import org.antlr.v4.runtime.tree.TerminalNode
 import javax.annotation.processing.ProcessingEnvironment
@@ -191,7 +192,7 @@
     fun getTypeMirrors(env: ProcessingEnvironment): List<TypeMirror>? {
         val typeUtils = env.typeUtils
         return when (this) {
-            TEXT -> listOf(env.elementUtils.getTypeElement("java.lang.String").asType())
+            TEXT -> listOf(env.requireTypeMirror("java.lang.String"))
             INTEGER -> withBoxedTypes(
                 env, TypeKind.INT, TypeKind.BYTE, TypeKind.CHAR,
                 TypeKind.LONG, TypeKind.SHORT
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
index 9eacbd3..408b149 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.RewriteQueriesToDropUnusedColumns
 import androidx.room.ext.hasAnnotation
+import androidx.room.ext.requireTypeMirror
 import androidx.room.log.RLog
 import androidx.room.parser.expansion.ProjectionExpander
 import androidx.room.parser.optimization.RemoveUnusedColumnQueryRewriter
@@ -96,13 +97,13 @@
 
     class CommonTypes(val processingEnv: ProcessingEnvironment) {
         val VOID: TypeMirror by lazy {
-            processingEnv.elementUtils.getTypeElement("java.lang.Void").asType()
+            processingEnv.requireTypeMirror("java.lang.Void")
         }
         val STRING: TypeMirror by lazy {
-            processingEnv.elementUtils.getTypeElement("java.lang.String").asType()
+            processingEnv.requireTypeMirror("java.lang.String")
         }
         val COLLECTION: TypeMirror by lazy {
-            processingEnv.elementUtils.getTypeElement("java.util.Collection").asType()
+            processingEnv.requireTypeMirror("java.util.Collection")
         }
     }
 
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
index 21c0735..7ccc6d1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
@@ -32,6 +32,7 @@
 import androidx.room.vo.KotlinDefaultMethodDelegate
 import com.google.auto.common.MoreTypes
 import com.squareup.javapoet.TypeName
+import isAssignableFrom
 import javax.lang.model.element.ElementKind
 import javax.lang.model.element.ExecutableElement
 import javax.lang.model.element.Modifier.ABSTRACT
@@ -158,7 +159,7 @@
         val typeUtils = context.processingEnv.typeUtils
         val goodConstructor = constructors.firstOrNull {
             it.parameters.size == 1 &&
-                    typeUtils.isAssignable(dbType, it.parameters[0].asType())
+                    it.parameters[0].asType().isAssignableFrom(typeUtils, dbType)
         }
         val constructorParamType = if (goodConstructor != null) {
             goodConstructor.parameters[0].asType().typeName()
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index feb2098..e99788b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.RoomTypeNames
 import androidx.room.ext.hasAnnotation
 import androidx.room.ext.hasAnyOf
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.toAnnotationBox
 import androidx.room.verifier.DatabaseVerificationErrors
 import androidx.room.verifier.DatabaseVerifier
@@ -36,6 +37,7 @@
 import com.google.auto.common.MoreElements
 import com.google.auto.common.MoreTypes
 import com.squareup.javapoet.TypeName
+import isAssignableFrom
 import java.util.Locale
 import javax.lang.model.element.Element
 import javax.lang.model.element.ElementKind
@@ -46,10 +48,9 @@
 class DatabaseProcessor(baseContext: Context, val element: TypeElement) {
     val context = baseContext.fork(element)
 
-    val baseClassElement: TypeMirror by lazy {
-        context.processingEnv.elementUtils.getTypeElement(
+    val roomDatabaseType: TypeMirror by lazy {
+        context.processingEnv.requireTypeMirror(
                 RoomTypeNames.ROOM_DB.packageName() + "." + RoomTypeNames.ROOM_DB.simpleName())
-                .asType()
     }
 
     fun process(): Database {
@@ -68,8 +69,11 @@
         validateForeignKeys(element, entities)
         validateExternalContentFts(element, entities)
 
-        val extendsRoomDb = context.processingEnv.typeUtils.isAssignable(
-                MoreElements.asType(element).asType(), baseClassElement)
+        val typeUtils = context.processingEnv.typeUtils
+        val extendsRoomDb = roomDatabaseType.isAssignableFrom(
+            typeUtils,
+            MoreElements.asType(element).asType()
+        )
         context.checker.check(extendsRoomDb, element, ProcessorErrors.DB_MUST_EXTEND_ROOM_DB)
 
         val allMembers = context.processingEnv.elementUtils.getAllMembers(element)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
index 1059368..bfd0191 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
@@ -22,6 +22,7 @@
 import androidx.room.FtsOptions.Order
 import androidx.room.ext.AnnotationBox
 import androidx.room.ext.hasAnnotation
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.toAnnotationBox
 import androidx.room.parser.FtsVersion
 import androidx.room.parser.SQLTypeAffinity
@@ -157,8 +158,7 @@
             return null
         }
 
-        val defaultType = context.processingEnv.elementUtils
-                    .getTypeElement(Object::class.java.canonicalName).asType()
+        val defaultType = context.processingEnv.requireTypeMirror(Object::class)
         if (context.processingEnv.typeUtils.isSameType(entityType, defaultType)) {
             return null
         }
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
index 6274c80..e40797e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
@@ -21,7 +21,9 @@
 import androidx.room.ext.N
 import androidx.room.ext.RoomCoroutinesTypeNames
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
 import androidx.room.ext.getSuspendFunctionReturnType
+import androidx.room.ext.requireTypeMirror
 import androidx.room.kotlin.KotlinMetadataElement
 import androidx.room.parser.ParsedQuery
 import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
@@ -98,8 +100,8 @@
             val kotlinMetadata =
                 KotlinMetadataElement.createFor(context, executableElement.enclosingElement)
             return if (kotlinMetadata?.isSuspendFunction(executableElement) == true) {
-                val hasCoroutineArtifact = context.processingEnv.elementUtils
-                    .getTypeElement(RoomCoroutinesTypeNames.COROUTINES_ROOM.toString()) != null
+                val hasCoroutineArtifact = context.processingEnv
+                    .findTypeElement(RoomCoroutinesTypeNames.COROUTINES_ROOM.toString()) != null
                 if (!hasCoroutineArtifact) {
                     context.logger.e(ProcessorErrors.MISSING_ROOM_COROUTINE_ARTIFACT)
                 }
@@ -172,9 +174,8 @@
     private val continuationParam: VariableElement by lazy {
         val typesUtil = context.processingEnv.typeUtils
         val continuationType = typesUtil.erasure(
-            context.processingEnv.elementUtils
-                .getTypeElement(KotlinTypeNames.CONTINUATION.toString())
-                .asType()
+            context.processingEnv
+                .requireTypeMirror(KotlinTypeNames.CONTINUATION.toString())
         )
         executableElement.parameters.last {
             typesUtil.isSameType(typesUtil.erasure(it.asType()), continuationType)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
index d787416..86f9cd1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -23,11 +23,12 @@
 import androidx.room.PrimaryKey
 import androidx.room.Relation
 import androidx.room.ext.extendsBoundOrSelf
+import androidx.room.ext.findTypeElement
 import androidx.room.ext.getAllFieldsIncludingPrivateSupers
 import androidx.room.ext.getAllMethodsIncludingSupers
 import androidx.room.ext.hasAnnotation
 import androidx.room.ext.hasAnyOf
-import androidx.room.ext.isAssignableWithoutVariance
+import androidx.room.ext.isAssignableFromWithoutVariance
 import androidx.room.ext.isCollection
 import androidx.room.ext.toAnnotationBox
 import androidx.room.ext.typeName
@@ -99,10 +100,10 @@
             referenceStack: LinkedHashSet<Name> = LinkedHashSet()
         ): PojoProcessor {
             val (pojoElement, delegate) = if (element.hasAnnotation(AutoValue::class)) {
-                val elementUtils = context.processingEnv.elementUtils
+                val processingEnv = context.processingEnv
                 val autoValueGeneratedElement = element.let {
                     val typeName = AutoValuePojoProcessorDelegate.getGeneratedClassName(it)
-                    elementUtils.getTypeElement(typeName) ?: throw MissingTypeException(typeName)
+                    processingEnv.findTypeElement(typeName) ?: throw MissingTypeException(typeName)
                 }
                 autoValueGeneratedElement to AutoValuePojoProcessorDelegate(context, element)
             } else {
@@ -313,7 +314,7 @@
                         false
                     } else {
                         // see: b/69164099
-                        typeUtils.isAssignableWithoutVariance(paramType, field.type)
+                        field.type.isAssignableFromWithoutVariance(typeUtils, paramType)
                     }
                 }
 
@@ -829,7 +830,7 @@
         val matching = candidates
                 .filter {
                     // b/69164099
-                    types.isAssignableWithoutVariance(getType(it), field.type) &&
+                    field.type.isAssignableFromWithoutVariance(types, getType(it)) &&
                             (field.nameWithVariations.contains(it.name) ||
                             nameVariations.contains(it.name))
                 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
index fd44206..bb38482 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.SupportDbTypeNames
 import androidx.room.ext.hasAnnotation
 import androidx.room.ext.isEntityElement
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.toAnnotationBox
 import androidx.room.ext.typeName
 import androidx.room.parser.SqlParser
@@ -28,6 +29,7 @@
 import androidx.room.vo.RawQueryMethod
 import asTypeElement
 import com.google.auto.common.MoreTypes
+import isAssignableFrom
 import javax.lang.model.element.ExecutableElement
 import javax.lang.model.element.VariableElement
 import javax.lang.model.type.DeclaredType
@@ -110,17 +112,16 @@
                     types,
                     containing,
                     extractParams[0])
-            val elementUtils = context.processingEnv.elementUtils
-            val supportQueryType = elementUtils
-                    .getTypeElement(SupportDbTypeNames.QUERY.toString()).asType()
-            val isSupportSql = types.isAssignable(param, supportQueryType)
+            val processingEnv = context.processingEnv
+            val supportQueryType = processingEnv.requireTypeMirror(SupportDbTypeNames.QUERY)
+            val isSupportSql = supportQueryType.isAssignableFrom(types, param)
             if (isSupportSql) {
                 return RawQueryMethod.RuntimeQueryParameter(
                         paramName = extractParams[0].simpleName.toString(),
                         type = supportQueryType.typeName())
             }
-            val stringType = elementUtils.getTypeElement("java.lang.String").asType()
-            val isString = types.isAssignable(param, stringType)
+            val stringType = processingEnv.requireTypeMirror("java.lang.String")
+            val isString = stringType.isAssignableFrom(types, param)
             if (isString) {
                 // special error since this was initially allowed but removed in 1.1 beta1
                 context.logger.e(executableElement, RAW_QUERY_STRING_PARAMETER_REMOVED)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
index d75f563..8b2621b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
@@ -17,8 +17,10 @@
 package androidx.room.processor
 
 import androidx.room.ext.extendsBound
+import androidx.room.ext.requireTypeMirror
 import androidx.room.vo.ShortcutQueryParameter
 import com.google.auto.common.MoreTypes
+import isAssignableFrom
 import javax.lang.model.element.TypeElement
 import javax.lang.model.element.VariableElement
 import javax.lang.model.type.ArrayType
@@ -54,6 +56,7 @@
     @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
     private fun extractPojoType(typeMirror: TypeMirror): Pair<TypeMirror?, Boolean> {
 
+        val processingEnv = context.processingEnv
         val elementUtils = context.processingEnv.elementUtils
         val typeUtils = context.processingEnv.typeUtils
 
@@ -80,9 +83,9 @@
             throw IllegalArgumentException("iterator() not found in Iterable $iterableType")
         }
 
-        val iterableType = typeUtils.erasure(elementUtils
-                .getTypeElement("java.lang.Iterable").asType())
-        if (typeUtils.isAssignable(typeMirror, iterableType)) {
+        val iterableType = typeUtils.erasure(processingEnv
+                .requireTypeMirror("java.lang.Iterable"))
+        if (iterableType.isAssignableFrom(typeUtils, typeMirror)) {
             val declared = MoreTypes.asDeclared(typeMirror)
             val pojo = extractPojoTypeFromIterator(declared)
             return verifyAndPair(pojo, true)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
index 8f987b9..506e422 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
@@ -21,8 +21,10 @@
 import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.RxJava3TypeNames
 import androidx.room.ext.findKotlinDefaultImpl
+import androidx.room.ext.findTypeMirror
 import androidx.room.ext.hasAnyOf
 import androidx.room.vo.TransactionMethod
+import isAssignableFrom
 import javax.lang.model.element.ExecutableElement
 import javax.lang.model.element.Modifier.ABSTRACT
 import javax.lang.model.element.Modifier.DEFAULT
@@ -40,19 +42,19 @@
 
     fun process(): TransactionMethod {
         val delegate = MethodProcessorDelegate.createFor(context, containing, executableElement)
-        val kotlinDefaultImpl =
-                executableElement.findKotlinDefaultImpl(context.processingEnv.typeUtils)
+        val typeUtils = context.processingEnv.typeUtils
+        val kotlinDefaultImpl = executableElement.findKotlinDefaultImpl(typeUtils)
         context.checker.check(
                 !executableElement.hasAnyOf(PRIVATE, FINAL) &&
                         (!executableElement.hasAnyOf(ABSTRACT) || kotlinDefaultImpl != null),
                 executableElement, ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
 
         val returnType = delegate.extractReturnType()
-        val erasureReturnType = context.processingEnv.typeUtils.erasure(returnType)
+        val erasureReturnType = typeUtils.erasure(returnType)
 
         DEFERRED_TYPES.firstOrNull { className ->
-            context.processingEnv.elementUtils.getTypeElement(className.toString())?.asType()?.let {
-                context.processingEnv.typeUtils.isAssignable(it, erasureReturnType)
+            context.processingEnv.findTypeMirror(className)?.let {
+                erasureReturnType.isAssignableFrom(typeUtils, it)
             } ?: false
         }?.let { returnTypeName ->
             context.logger.e(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index dcb598e..1c31fff 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -19,7 +19,7 @@
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaBaseTypeNames
 import androidx.room.ext.extendsBoundOrSelf
-import androidx.room.ext.isAssignableWithoutVariance
+import androidx.room.ext.isAssignableFromWithoutVariance
 import androidx.room.ext.isEntityElement
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
@@ -96,6 +96,7 @@
 import com.google.auto.common.MoreTypes
 import com.google.common.annotations.VisibleForTesting
 import com.google.common.collect.ImmutableList
+import isAssignableFrom
 import java.util.LinkedList
 import javax.lang.model.type.ArrayType
 import javax.lang.model.type.TypeKind
@@ -512,8 +513,11 @@
 
     fun findQueryParameterAdapter(typeMirror: TypeMirror): QueryParameterAdapter? {
         val typeUtils = context.processingEnv.typeUtils
-        if (MoreTypes.isType(typeMirror) && typeUtils.isAssignable(typeMirror,
-                typeUtils.erasure(context.COMMON_TYPES.COLLECTION))) {
+        if (MoreTypes.isType(typeMirror) &&
+            typeUtils.erasure(context.COMMON_TYPES.COLLECTION).isAssignableFrom(
+                typeUtils,
+                typeMirror
+            )) {
             val declared = MoreTypes.asDeclared(typeMirror)
             val binder = findStatementValueBinder(
                 declared.typeArguments.first().extendsBoundOrSelf(), null)
@@ -561,7 +565,7 @@
         val queue = LinkedList<TypeConverter>()
         fun exactMatch(candidates: List<TypeConverter>): TypeConverter? {
             return candidates.firstOrNull {
-                outputs.any { output -> types.isAssignableWithoutVariance(output, it.to) }
+                outputs.any { output -> it.to.isAssignableFromWithoutVariance(types, output) }
             }
         }
         inputs.forEach { input ->
@@ -609,7 +613,7 @@
         // for input, check assignability because it defines whether we can use the method or not.
         // for excludes, use exact match
         return typeConverters.filter { converter ->
-            types.isAssignable(input, converter.from) &&
+            converter.from.isAssignableFrom(types, input) &&
                     !excludes.any { types.isSameType(it, converter.to) }
         }.sortedByDescending {
             // if it is the same, prioritize
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
index b419a57..7c3d918 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
@@ -27,8 +27,19 @@
 import androidx.room.solver.query.result.QueryResultBinder
 import javax.lang.model.type.DeclaredType
 
-class CoroutineFlowResultBinderProvider(val context: Context) : QueryResultBinderProvider {
+@Suppress("FunctionName")
+fun CoroutineFlowResultBinderProvider(context: Context): QueryResultBinderProvider =
+    CoroutineFlowResultBinderProviderImpl(
+        context
+    ).requireArtifact(
+        context = context,
+        requiredType = RoomCoroutinesTypeNames.COROUTINES_ROOM,
+        missingArtifactErrorMsg = ProcessorErrors.MISSING_ROOM_COROUTINE_ARTIFACT
+    )
 
+private class CoroutineFlowResultBinderProviderImpl(
+    val context: Context
+) : QueryResultBinderProvider {
     companion object {
         val CHANNEL_TYPE_NAMES = listOf(
             KotlinTypeNames.CHANNEL,
@@ -37,11 +48,6 @@
         )
     }
 
-    private val hasCoroutinesArtifact by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(RoomCoroutinesTypeNames.COROUTINES_ROOM.toString()) != null
-    }
-
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
         val typeArg = declared.typeArguments.first()
         val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
@@ -62,10 +68,6 @@
             context.logger.e(ProcessorErrors.invalidChannelType(typeName.toString()))
             return false
         }
-        val match = typeName == KotlinTypeNames.FLOW
-        if (match && !hasCoroutinesArtifact) {
-            context.logger.e(ProcessorErrors.MISSING_ROOM_COROUTINE_ARTIFACT)
-        }
-        return match
+        return typeName == KotlinTypeNames.FLOW
     }
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
index e49acba..d01d1b8 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
@@ -17,6 +17,7 @@
 package androidx.room.solver.binderprovider
 
 import androidx.room.ext.PagingTypeNames
+import androidx.room.ext.findTypeMirror
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
 import androidx.room.processor.ProcessorErrors
@@ -25,13 +26,13 @@
 import androidx.room.solver.query.result.ListQueryResultAdapter
 import androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder
 import androidx.room.solver.query.result.QueryResultBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 class DataSourceFactoryQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
     private val dataSourceFactoryTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY.toString())?.asType()
+        context.processingEnv.findTypeMirror(PagingTypeNames.DATA_SOURCE_FACTORY)
     }
 
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
@@ -56,8 +57,12 @@
         if (dataSourceFactoryTypeMirror == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
         // we don't want to return paged list unless explicitly requested
-        return context.processingEnv.typeUtils.isAssignable(dataSourceFactoryTypeMirror, erasure)
+        return erasure.isAssignableFrom(
+            typeUtils,
+            dataSourceFactoryTypeMirror!!
+        )
     }
 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
index 5c55a44..fe57782 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
@@ -17,6 +17,7 @@
 package androidx.room.solver.binderprovider
 
 import androidx.room.ext.PagingTypeNames
+import androidx.room.ext.findTypeMirror
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
 import androidx.room.processor.ProcessorErrors
@@ -24,18 +25,17 @@
 import androidx.room.solver.query.result.ListQueryResultAdapter
 import androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder
 import androidx.room.solver.query.result.QueryResultBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 class DataSourceQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
     private val dataSourceTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(PagingTypeNames.DATA_SOURCE.toString())?.asType()
+        context.processingEnv.findTypeMirror(PagingTypeNames.DATA_SOURCE)
     }
 
     private val positionalDataSourceTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(PagingTypeNames.POSITIONAL_DATA_SOURCE.toString())?.asType()
+        context.processingEnv.findTypeMirror(PagingTypeNames.POSITIONAL_DATA_SOURCE)
     }
 
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
@@ -58,14 +58,18 @@
         if (declared.typeArguments.isEmpty()) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        val isDataSource = context.processingEnv.typeUtils
-                .isAssignable(erasure, dataSourceTypeMirror)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        val isDataSource = dataSourceTypeMirror!!.isAssignableFrom(
+            typeUtils,
+            erasure
+        )
         if (!isDataSource) {
             return false
         }
-        val isPositional = context.processingEnv.typeUtils
-                .isAssignable(erasure, positionalDataSourceTypeMirror)
+        val isPositional = positionalDataSourceTypeMirror!!.isAssignableFrom(
+            typeUtils, erasure
+        )
         if (!isPositional) {
             context.logger.e(ProcessorErrors.PAGING_SPECIFY_DATA_SOURCE_TYPE)
         }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
index 3934a66..db574aff 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
@@ -27,14 +27,19 @@
 import androidx.room.solver.query.result.QueryResultBinder
 import javax.lang.model.type.DeclaredType
 
-class GuavaListenableFutureQueryResultBinderProvider(val context: Context) :
-    QueryResultBinderProvider {
+@Suppress("FunctionName")
+fun GuavaListenableFutureQueryResultBinderProvider(context: Context): QueryResultBinderProvider =
+    GuavaListenableFutureQueryResultBinderProviderImpl(
+        context = context
+    ).requireArtifact(
+        context = context,
+        requiredType = RoomGuavaTypeNames.GUAVA_ROOM,
+        missingArtifactErrorMsg = ProcessorErrors.MISSING_ROOM_GUAVA_ARTIFACT
+    )
 
-    private val hasGuavaRoom by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(RoomGuavaTypeNames.GUAVA_ROOM.toString()) != null
-    }
-
+class GuavaListenableFutureQueryResultBinderProviderImpl(
+    val context: Context
+) : QueryResultBinderProvider {
     /**
      * Returns the {@link GuavaListenableFutureQueryResultBinder} instance for the input type, if
      * possible.
@@ -42,10 +47,6 @@
      * <p>Emits a compiler error if the Guava Room extension library is not linked.
      */
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
-        if (!hasGuavaRoom) {
-            context.logger.e(ProcessorErrors.MISSING_ROOM_GUAVA_ARTIFACT)
-        }
-
         // Use the type T inside ListenableFuture<T> as the type to adapt and to pass into
         // the binder.
         val adapter = context.typeAdapterStore.findQueryResultAdapter(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
index 41352f1..ad73e34 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
@@ -17,19 +17,20 @@
 package androidx.room.solver.binderprovider
 
 import androidx.room.ext.LifecyclesTypeNames
+import androidx.room.ext.findTypeMirror
 import androidx.room.processor.Context
 import androidx.room.solver.ObservableQueryResultBinderProvider
 import androidx.room.solver.query.result.LiveDataQueryResultBinder
 import androidx.room.solver.query.result.QueryResultAdapter
 import androidx.room.solver.query.result.QueryResultBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 class LiveDataQueryResultBinderProvider(context: Context) :
     ObservableQueryResultBinderProvider(context) {
     private val liveDataTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(LifecyclesTypeNames.LIVE_DATA.toString())?.asType()
+        context.processingEnv.findTypeMirror(LifecyclesTypeNames.LIVE_DATA)
     }
 
     override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
@@ -52,7 +53,8 @@
         if (liveDataTypeMirror == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        return context.processingEnv.typeUtils.isAssignable(liveDataTypeMirror, erasure)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        return erasure.isAssignableFrom(typeUtils, liveDataTypeMirror!!)
     }
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
index f89b7c8..b1e7f97 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
@@ -17,6 +17,7 @@
 package androidx.room.solver.binderprovider
 
 import androidx.room.ext.PagingTypeNames
+import androidx.room.ext.findTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
@@ -27,13 +28,13 @@
 import androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder
 import androidx.room.solver.query.result.QueryResultBinder
 import com.squareup.javapoet.TypeName
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 class PagingSourceQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
     private val pagingSourceTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(PagingTypeNames.PAGING_SOURCE.toString())?.asType()
+        context.processingEnv.findTypeMirror(PagingTypeNames.PAGING_SOURCE)
     }
 
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
@@ -60,8 +61,9 @@
             return false
         }
 
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        if (!context.processingEnv.typeUtils.isAssignable(erasure, pagingSourceTypeMirror)) {
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        if (!pagingSourceTypeMirror!!.isAssignableFrom(typeUtils, erasure)) {
             return false
         }
 
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/QueryResultBinderProviderWithRequiredArtifact.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/QueryResultBinderProviderWithRequiredArtifact.kt
new file mode 100644
index 0000000..2a6c57a
--- /dev/null
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/QueryResultBinderProviderWithRequiredArtifact.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 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 androidx.room.solver.binderprovider
+
+import androidx.room.ext.findTypeElement
+import androidx.room.parser.ParsedQuery
+import androidx.room.processor.Context
+import androidx.room.solver.QueryResultBinderProvider
+import androidx.room.solver.query.result.QueryResultBinder
+import com.squareup.javapoet.TypeName
+import javax.lang.model.type.DeclaredType
+
+/**
+ * Common functionality for binder providers that require an additional artifact
+ */
+fun QueryResultBinderProvider.requireArtifact(
+    context: Context,
+    requiredType: TypeName,
+    missingArtifactErrorMsg: String
+): QueryResultBinderProvider = QueryResultBinderProviderWithRequiredArtifact(
+    context = context,
+    requiredType = requiredType,
+    missingArtifactErrorMsg = missingArtifactErrorMsg,
+    delegate = this
+)
+
+private class QueryResultBinderProviderWithRequiredArtifact(
+    val context: Context,
+    val requiredType: TypeName,
+    val missingArtifactErrorMsg: String,
+    val delegate: QueryResultBinderProvider
+) : QueryResultBinderProvider {
+    private val hasRequiredArtifact by lazy(LazyThreadSafetyMode.NONE) {
+        context.processingEnv.findTypeElement(requiredType) != null
+    }
+
+    override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
+        return delegate.provide(declared, query)
+    }
+
+    override fun matches(declared: DeclaredType): Boolean {
+        val result = delegate.matches(declared)
+        if (result && !hasRequiredArtifact) {
+            context.logger.e(missingArtifactErrorMsg)
+        }
+        return result
+    }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
index 5808a3f..0d32121 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
@@ -29,11 +29,6 @@
     val context: Context,
     private val rxType: RxType
 ) : QueryResultBinderProvider {
-    private val hasRxJavaArtifact by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
-    }
-
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
         val typeArg = declared.typeArguments.first()
         val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
@@ -45,11 +40,7 @@
 
     private fun matchesRxType(declared: DeclaredType): Boolean {
         val erasure = context.processingEnv.typeUtils.erasure(declared)
-        val match = erasure.typeName() == rxType.className
-        if (match && !hasRxJavaArtifact) {
-            context.logger.e(rxType.version.missingArtifactMessage)
-        }
-        return match
+        return erasure.typeName() == rxType.className
     }
 
     companion object {
@@ -58,6 +49,12 @@
             RxType.RX2_MAYBE,
             RxType.RX3_SINGLE,
             RxType.RX3_MAYBE
-        ).map { RxCallableQueryResultBinderProvider(context, it) }
+        ).map {
+            RxCallableQueryResultBinderProvider(context, it).requireArtifact(
+                context = context,
+                requiredType = it.version.rxRoomClassName,
+                missingArtifactErrorMsg = it.version.missingArtifactMessage
+            )
+        }
     }
 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
index a96b7d8..ee5253c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
@@ -16,12 +16,14 @@
 
 package androidx.room.solver.binderprovider
 
+import androidx.room.ext.findTypeMirror
 import androidx.room.processor.Context
 import androidx.room.solver.ObservableQueryResultBinderProvider
 import androidx.room.solver.RxType
 import androidx.room.solver.query.result.QueryResultAdapter
 import androidx.room.solver.query.result.QueryResultBinder
 import androidx.room.solver.query.result.RxQueryResultBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
@@ -30,12 +32,7 @@
     private val rxType: RxType
 ) : ObservableQueryResultBinderProvider(context) {
     private val typeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(rxType.className.toString())?.asType()
-    }
-    private val hasRxJavaArtifact by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
+        context.processingEnv.findTypeMirror(rxType.className)
     }
 
     override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
@@ -60,12 +57,9 @@
         if (typeMirror == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        val match = context.processingEnv.typeUtils.isAssignable(typeMirror, erasure)
-        if (match && !hasRxJavaArtifact) {
-            context.logger.e(rxType.version.missingArtifactMessage)
-        }
-        return match
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        return erasure.isAssignableFrom(typeUtils, typeMirror!!)
     }
 
     companion object {
@@ -74,6 +68,12 @@
             RxType.RX2_OBSERVABLE,
             RxType.RX3_FLOWABLE,
             RxType.RX3_OBSERVABLE
-        ).map { RxQueryResultBinderProvider(context, it) }
+        ).map {
+            RxQueryResultBinderProvider(context, it).requireArtifact(
+                context = context,
+                requiredType = it.version.rxRoomClassName,
+                missingArtifactErrorMsg = it.version.missingArtifactMessage
+            )
+        }
     }
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
index 9ecc94d..9c3ee1a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.N
 import androidx.room.ext.RoomGuavaTypeNames
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
@@ -33,8 +34,7 @@
     PreparedQueryResultBinderProvider {
 
     private val hasGuavaRoom by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(RoomGuavaTypeNames.GUAVA_ROOM.toString()) != null
+        context.processingEnv.findTypeElement(RoomGuavaTypeNames.GUAVA_ROOM) != null
     }
 
     override fun matches(declared: DeclaredType): Boolean =
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
index c1ade4a..8b3d052 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
@@ -18,12 +18,15 @@
 
 import androidx.room.ext.L
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
+import androidx.room.ext.findTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
 import androidx.room.solver.RxType
 import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
 import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
@@ -33,8 +36,7 @@
 ) : PreparedQueryResultBinderProvider {
 
     private val hasRxJavaArtifact by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
+        context.processingEnv.findTypeElement(rxType.version.rxRoomClassName) != null
     }
 
     override fun matches(declared: DeclaredType): Boolean =
@@ -78,16 +80,16 @@
 ) : RxPreparedQueryResultBinderProvider(context, rxType) {
 
     private val completableType: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(rxType.className.toString())?.asType()
+        context.processingEnv.findTypeMirror(rxType.className)
     }
 
     override fun matches(declared: DeclaredType): Boolean {
         if (completableType == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        return context.processingEnv.typeUtils.isAssignable(completableType, erasure)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        return erasure.isAssignableFrom(typeUtils, completableType!!)
     }
 
     override fun extractTypeArg(declared: DeclaredType) = context.COMMON_TYPES.VOID
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
index 106bc14..9961244 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.N
 import androidx.room.ext.RoomGuavaTypeNames
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
 import androidx.room.processor.ProcessorErrors
@@ -36,8 +37,7 @@
 ) : DeleteOrUpdateMethodBinderProvider {
 
     private val hasGuavaRoom by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(RoomGuavaTypeNames.GUAVA_ROOM.toString()) != null
+        context.processingEnv.findTypeElement(RoomGuavaTypeNames.GUAVA_ROOM) != null
     }
 
     override fun matches(declared: DeclaredType): Boolean =
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
index f603510..5f6ea59 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
@@ -21,6 +21,7 @@
 import androidx.room.ext.N
 import androidx.room.ext.RoomGuavaTypeNames
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
 import androidx.room.processor.ProcessorErrors
@@ -37,8 +38,7 @@
 ) : InsertMethodBinderProvider {
 
     private val hasGuavaRoom by lazy {
-        context.processingEnv.elementUtils
-            .getTypeElement(RoomGuavaTypeNames.GUAVA_ROOM.toString()) != null
+        context.processingEnv.findTypeElement(RoomGuavaTypeNames.GUAVA_ROOM) != null
     }
 
     override fun matches(declared: DeclaredType): Boolean =
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
index 0a9518c..23318bf 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
@@ -18,11 +18,13 @@
 
 import androidx.room.ext.L
 import androidx.room.ext.T
+import androidx.room.ext.findTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
 import androidx.room.solver.RxType
 import androidx.room.solver.shortcut.binder.CallableDeleteOrUpdateMethodBinder.Companion.createDeleteOrUpdateBinder
 import androidx.room.solver.shortcut.binder.DeleteOrUpdateMethodBinder
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
@@ -74,8 +76,7 @@
 ) : RxCallableDeleteOrUpdateMethodBinderProvider(context, rxType) {
 
     private val completableTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(rxType.className.toString())?.asType()
+        context.processingEnv.findTypeMirror(rxType.className)
     }
 
     /**
@@ -91,7 +92,8 @@
         if (completableTypeMirror == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        return context.processingEnv.typeUtils.isAssignable(completableTypeMirror, erasure)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        return erasure.isAssignableFrom(typeUtils, completableTypeMirror!!)
     }
 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
index 923a748..e5a4765 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
@@ -18,12 +18,14 @@
 
 import androidx.room.ext.L
 import androidx.room.ext.T
+import androidx.room.ext.findTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
 import androidx.room.solver.RxType
 import androidx.room.solver.shortcut.binder.CallableInsertMethodBinder.Companion.createInsertBinder
 import androidx.room.solver.shortcut.binder.InsertMethodBinder
 import androidx.room.vo.ShortcutQueryParameter
+import isAssignableFrom
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
@@ -78,8 +80,7 @@
 ) : RxCallableInsertMethodBinderProvider(context, rxType) {
 
     private val completableTypeMirror: TypeMirror? by lazy {
-        context.processingEnv.elementUtils
-                .getTypeElement(rxType.className.toString())?.asType()
+        context.processingEnv.findTypeMirror(rxType.className)
     }
 
     /**
@@ -95,7 +96,8 @@
         if (completableTypeMirror == null) {
             return false
         }
-        val erasure = context.processingEnv.typeUtils.erasure(declared)
-        return context.processingEnv.typeUtils.isAssignable(completableTypeMirror, erasure)
+        val typeUtils = context.processingEnv.typeUtils
+        val erasure = typeUtils.erasure(declared)
+        return erasure.isAssignableFrom(typeUtils, completableTypeMirror!!)
     }
 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
index 015ede9..fd8d789 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
@@ -17,6 +17,7 @@
 package androidx.room.solver.types
 
 import androidx.room.ext.L
+import androidx.room.ext.requireTypeMirror
 import androidx.room.solver.CodeGenScope
 import javax.annotation.processing.ProcessingEnvironment
 
@@ -25,10 +26,8 @@
  */
 object BoxedBooleanToBoxedIntConverter {
     fun create(processingEnvironment: ProcessingEnvironment): List<TypeConverter> {
-        val tBoolean = processingEnvironment.elementUtils.getTypeElement("java.lang.Boolean")
-                .asType()
-        val tInt = processingEnvironment.elementUtils.getTypeElement("java.lang.Integer")
-                .asType()
+        val tBoolean = processingEnvironment.requireTypeMirror("java.lang.Boolean")
+        val tInt = processingEnvironment.requireTypeMirror("java.lang.Integer")
         return listOf(
                 object : TypeConverter(tBoolean, tInt) {
                     override fun convert(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
index 95dfb99..1289f08 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.ext.L
 import androidx.room.ext.T
+import androidx.room.ext.requireTypeMirror
 import androidx.room.parser.SQLTypeAffinity
 import androidx.room.solver.CodeGenScope
 import com.squareup.javapoet.TypeName
@@ -25,7 +26,7 @@
 import javax.annotation.processing.ProcessingEnvironment
 
 class ByteBufferColumnTypeAdapter(env: ProcessingEnvironment) : ColumnTypeAdapter(
-    out = env.elementUtils.getTypeElement("java.nio.ByteBuffer").asType(),
+    out = env.requireTypeMirror("java.nio.ByteBuffer"),
     typeAffinity = SQLTypeAffinity.BLOB
 ) {
     override fun readFromCursor(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
index 2fe0e91..2a8fa53 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
@@ -17,13 +17,13 @@
 package androidx.room.solver.types
 
 import androidx.room.ext.L
+import androidx.room.ext.requireTypeMirror
 import androidx.room.parser.SQLTypeAffinity.TEXT
 import androidx.room.solver.CodeGenScope
 import javax.annotation.processing.ProcessingEnvironment
 
 class StringColumnTypeAdapter(processingEnvironment: ProcessingEnvironment) :
-    ColumnTypeAdapter((processingEnvironment.elementUtils.getTypeElement(
-        String::class.java.canonicalName)).asType(), TEXT) {
+    ColumnTypeAdapter((processingEnvironment.requireTypeMirror(String::class)), TEXT) {
     override fun readFromCursor(
         outVarName: String,
         cursorVarName: String,
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt b/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
index 1b536d1..54557cc 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
@@ -21,6 +21,9 @@
 import androidx.room.ext.L
 import androidx.room.ext.N
 import androidx.room.ext.T
+import androidx.room.ext.findTypeElement
+import androidx.room.ext.requireTypeElement
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.parser.SQLTypeAffinity
@@ -249,8 +252,8 @@
                 val usingLongSparseArray =
                     tmpMapType.rawType == CollectionTypeNames.LONG_SPARSE_ARRAY
                 val queryParam = if (usingLongSparseArray) {
-                    val longSparseArrayElement = context.processingEnv.elementUtils
-                            .getTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY.toString())
+                    val longSparseArrayElement = context.processingEnv
+                            .requireTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY)
                     QueryParameter(
                             name = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
                             sqlName = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
@@ -259,7 +262,7 @@
                     )
                 } else {
                     val keyTypeMirror = keyTypeMirrorFor(context, affinity)
-                    val set = context.processingEnv.elementUtils.getTypeElement("java.util.Set")
+                    val set = context.processingEnv.requireTypeElement("java.util.Set")
                     val keySet = context.processingEnv.typeUtils.getDeclaredType(set, keyTypeMirror)
                     QueryParameter(
                             name = RelationCollectorMethodWriter.KEY_SET_VARIABLE,
@@ -389,10 +392,10 @@
             keyType: TypeName,
             relationTypeName: TypeName
         ): ParameterizedTypeName {
-            val canUseLongSparseArray = context.processingEnv.elementUtils
-                .getTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY.toString()) != null
-            val canUseArrayMap = context.processingEnv.elementUtils
-                .getTypeElement(CollectionTypeNames.ARRAY_MAP.toString()) != null
+            val canUseLongSparseArray = context.processingEnv
+                .findTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY) != null
+            val canUseArrayMap = context.processingEnv
+                .findTypeElement(CollectionTypeNames.ARRAY_MAP) != null
             return when {
                 canUseLongSparseArray && affinity == SQLTypeAffinity.INTEGER -> {
                     ParameterizedTypeName.get(CollectionTypeNames.LONG_SPARSE_ARRAY,
@@ -411,12 +414,12 @@
 
         // Gets the type mirror of the relationship key.
         private fun keyTypeMirrorFor(context: Context, affinity: SQLTypeAffinity): TypeMirror {
-            val elements = context.processingEnv.elementUtils
+            val processingEnv = context.processingEnv
             return when (affinity) {
-                SQLTypeAffinity.INTEGER -> elements.getTypeElement("java.lang.Long").asType()
-                SQLTypeAffinity.REAL -> elements.getTypeElement("java.lang.Double").asType()
+                SQLTypeAffinity.INTEGER -> processingEnv.requireTypeMirror("java.lang.Long")
+                SQLTypeAffinity.REAL -> processingEnv.requireTypeMirror("java.lang.Double")
                 SQLTypeAffinity.TEXT -> context.COMMON_TYPES.STRING
-                SQLTypeAffinity.BLOB -> elements.getTypeElement("java.nio.ByteBuffer").asType()
+                SQLTypeAffinity.BLOB -> processingEnv.requireTypeMirror("java.nio.ByteBuffer")
                 else -> {
                     context.COMMON_TYPES.STRING
                 }
diff --git a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
index 5d89402..5118848 100644
--- a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.kotlin
 
+import androidx.room.ext.requireTypeElement
 import androidx.room.processor.Context
 import androidx.room.testing.TestInvocation
 import com.google.auto.common.MoreElements
@@ -97,7 +98,7 @@
     }
 
     private fun getMetadataElement(invocation: TestInvocation, klass: KClass<*>) =
-        invocation.typeElement(klass.java.canonicalName!!).let {
+        invocation.processingEnv.requireTypeElement(klass).let {
             it to KotlinMetadataElement.createFor(Context(invocation.processingEnv), it)!!
         }
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
index 7226809..5e13336 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
@@ -2,6 +2,7 @@
 
 import COMMON
 import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.requireTypeElement
 import androidx.room.vo.Dao
 import androidx.room.writer.DaoWriter
 import com.google.auto.common.MoreTypes
@@ -158,9 +159,9 @@
             }
         """.toJFO("foo.bar.MyDao")
         simpleRun(baseClass, extension, COMMON.USER) { invocation ->
-            val daoElm = invocation.processingEnv.elementUtils.getTypeElement("foo.bar.MyDao")
-            val dbElm = invocation.context.processingEnv.elementUtils
-                .getTypeElement(RoomTypeNames.ROOM_DB.toString())
+            val daoElm = invocation.processingEnv.requireTypeElement("foo.bar.MyDao")
+            val dbElm = invocation.context.processingEnv
+                .requireTypeElement(RoomTypeNames.ROOM_DB)
             val dbType = MoreTypes.asDeclared(dbElm.asType())
             val processedDao = DaoProcessor(
                 invocation.context, daoElm, dbType, null
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
index fe9474e..c2e98ff 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
@@ -17,6 +17,7 @@
 package androidx.room.processor
 
 import androidx.room.TypeConverter
+import androidx.room.ext.requireTypeElement
 import androidx.room.ext.typeName
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_EMPTY_CLASS
 import androidx.room.processor.ProcessorErrors
@@ -207,7 +208,7 @@
                         }.build().toString())
 
         simpleRun(baseConverter, extendingClass) { invocation ->
-            val element = invocation.processingEnv.elementUtils.getTypeElement(extendingQName)
+            val element = invocation.processingEnv.requireTypeElement(extendingQName)
             val converter = CustomConverterProcessor(invocation.context, element)
                     .process().firstOrNull()
             assertThat(converter?.fromTypeName, `is`(ParameterizedTypeName.get(
@@ -264,7 +265,7 @@
     ): CompileTester {
         return simpleRun(*((jfo.toList() + CONTAINER).toTypedArray())) { invocation ->
             val processed = CustomConverterProcessor.findConverters(invocation.context,
-                    invocation.processingEnv.elementUtils.getTypeElement("foo.bar.Container"))
+                    invocation.processingEnv.requireTypeElement("foo.bar.Container"))
             handler(processed.converters.firstOrNull()?.custom, invocation)
         }
     }
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
index 8e90716..1204399 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
@@ -18,6 +18,7 @@
 
 import COMMON
 import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.requireTypeMirror
 import androidx.room.testing.TestInvocation
 import androidx.room.testing.TestProcessor
 import androidx.room.vo.Dao
@@ -168,8 +169,8 @@
                 abstract User users();
             }
             """) { dao, invocation ->
-            val dbType = MoreTypes.asDeclared(invocation.context.processingEnv.elementUtils
-                    .getTypeElement(RoomTypeNames.ROOM_DB.toString()).asType())
+            val dbType = MoreTypes.asDeclared(invocation.context.processingEnv
+                    .requireTypeMirror(RoomTypeNames.ROOM_DB.toString()))
             val daoProcessor =
                 DaoProcessor(invocation.context, dao.element, dbType, null)
 
@@ -197,8 +198,8 @@
                 abstract User users();
             }
             """) { dao, invocation ->
-            val dbType = MoreTypes.asDeclared(invocation.context.processingEnv.elementUtils
-                    .getTypeElement(RoomTypeNames.ROOM_DB.toString()).asType())
+            val dbType = MoreTypes.asDeclared(invocation.context.processingEnv
+                    .requireTypeMirror(RoomTypeNames.ROOM_DB))
             val daoProcessor =
                 DaoProcessor(invocation.context, dao.element, dbType, null)
             assertThat(daoProcessor.context.logger
@@ -328,9 +329,8 @@
                                 null
                             }
                             val dbType = MoreTypes.asDeclared(
-                                    invocation.context.processingEnv.elementUtils
-                                            .getTypeElement(RoomTypeNames.ROOM_DB.toString())
-                                            .asType())
+                                    invocation.context.processingEnv
+                                            .requireTypeMirror(RoomTypeNames.ROOM_DB))
                             val parser = DaoProcessor(invocation.context,
                                     MoreElements.asType(dao), dbType, dbVerifier)
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
index 71d2a72f..0ddeee5 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
@@ -17,6 +17,7 @@
 package androidx.room.processor
 
 import androidx.room.Entity
+import androidx.room.ext.requireTypeMirror
 import androidx.room.parser.Collate
 import androidx.room.parser.SQLTypeAffinity
 import androidx.room.solver.types.ColumnTypeAdapter
@@ -106,7 +107,7 @@
         }
 
         private fun TypeKind.box(invocation: TestInvocation): TypeMirror {
-            return invocation.processingEnv.elementUtils.getTypeElement(box()).asType()
+            return invocation.processingEnv.requireTypeMirror(box())
         }
     }
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
index a4f4afc..dda7928 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.processor
 
+import androidx.room.ext.requireTypeElement
 import com.google.testing.compile.CompileTester
 import com.squareup.javapoet.ClassName
 import org.junit.Test
@@ -404,7 +405,7 @@
 
     private fun singleRun(vararg jfos: JavaFileObject) = simpleRun(*jfos) { invocation ->
         PojoProcessor.createFor(context = invocation.context,
-            element = invocation.typeElement(MY_POJO.toString()),
+            element = invocation.processingEnv.requireTypeElement(MY_POJO),
             bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
             parent = null).process()
     }
@@ -439,7 +440,7 @@
         val all = (jfos.toList() + pojoJFO + autoValuePojoJFO).toTypedArray()
         return simpleRun(*all) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                 parent = null).process()
         }
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
index 2afa385..26f7d81 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
@@ -18,6 +18,7 @@
 
 import COMMON
 import androidx.room.Embedded
+import androidx.room.ext.requireTypeElement
 import androidx.room.parser.SQLTypeAffinity
 import androidx.room.processor.ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD
 import androidx.room.processor.ProcessorErrors.CANNOT_FIND_TYPE
@@ -93,7 +94,7 @@
                 """.toJFO(MY_POJO.toString()),
                 parent.toJFO("foo.bar.x.BaseClass")) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
             assertThat(pojo.fields.find { it.name == "myField" }, notNullValue())
@@ -847,7 +848,7 @@
             $FOOTER
             """.toJFO(MY_POJO.toString())
         simpleRun(pojo) { invocation ->
-            val element = invocation.typeElement(MY_POJO.toString())
+            val element = invocation.processingEnv.requireTypeElement(MY_POJO)
             val pojo1 = PojoProcessor.createFor(invocation.context, element,
                     FieldProcessor.BindingScope.BIND_TO_STMT, null).process()
             assertThat(pojo1, notNullValue())
@@ -1029,7 +1030,7 @@
             String mLastName;
         """) { _, invocation ->
             val process2 = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
                     parent = null).process()
             assertThat(process2.constructor, nullValue())
@@ -1043,7 +1044,7 @@
             String mLastName;
         """) { _, invocation ->
             val process2 = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.TWO_WAY,
                     parent = null).process()
             assertThat(process2.constructor, notNullValue())
@@ -1336,7 +1337,7 @@
             simpleRun { invocation ->
                 PojoProcessor.createFor(
                         context = invocation.context,
-                        element = invocation.typeElement(it),
+                        element = invocation.processingEnv.requireTypeElement(it),
                         bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                         parent = null
                 ).process()
@@ -1349,8 +1350,8 @@
         simpleRun { invocation ->
             PojoProcessor.createFor(
                     context = invocation.context,
-                    element = invocation.typeElement(
-                            TestData.WithJvmOverloads::class.java.canonicalName!!
+                    element = invocation.processingEnv.requireTypeElement(
+                            TestData.WithJvmOverloads::class
                     ),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null
@@ -1372,7 +1373,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
             assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
@@ -1403,7 +1404,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
             assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
@@ -1433,7 +1434,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                 parent = null).process()
             assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
@@ -1456,7 +1457,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
             assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
@@ -1478,7 +1479,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             val pojo = PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
             assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
@@ -1502,7 +1503,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
                 parent = null).process()
         }.compilesWithoutError()
@@ -1523,7 +1524,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.TWO_WAY,
                 parent = null).process()
         }.failsToCompile().withErrorContaining("Cannot find setter for field.")
@@ -1544,7 +1545,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                 parent = null).process()
         }.failsToCompile().withErrorContaining("Cannot find setter for field.")
@@ -1565,7 +1566,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
                 parent = null).process()
         }.failsToCompile().withErrorContaining("Cannot find getter for field.")
@@ -1586,7 +1587,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.TWO_WAY,
                 parent = null).process()
         }.failsToCompile().withErrorContaining("Cannot find getter for field.")
@@ -1607,7 +1608,7 @@
                 }
                 """.toJFO(MY_POJO.toString())) { invocation ->
             PojoProcessor.createFor(context = invocation.context,
-                element = invocation.typeElement(MY_POJO.toString()),
+                element = invocation.processingEnv.requireTypeElement(MY_POJO),
                 bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                 parent = null).process()
         }.compilesWithoutError()
@@ -1653,7 +1654,7 @@
         return simpleRun(*all, classpathFiles = classpathFiles) { invocation ->
             handler.invoke(
                 PojoProcessor.createFor(context = invocation.context,
-                        element = invocation.typeElement(MY_POJO.toString()),
+                        element = invocation.processingEnv.requireTypeElement(MY_POJO),
                         bindingScope = FieldProcessor.BindingScope.TWO_WAY,
                         parent = null).process(),
                 invocation
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
index dd82041..c3d1173 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
@@ -24,6 +24,7 @@
 import androidx.room.ext.LifecyclesTypeNames
 import androidx.room.ext.PagingTypeNames
 import androidx.room.ext.hasAnnotation
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.parser.QueryType
 import androidx.room.parser.Table
@@ -372,8 +373,8 @@
                 }
                 """) { parsedQuery, invocation ->
             assertThat(parsedQuery.parameters.first().type,
-                    `is`(invocation.processingEnv.elementUtils
-                            .getTypeElement("java.lang.Integer").asType()))
+                    `is`(invocation.processingEnv
+                            .requireTypeMirror("java.lang.Integer")))
         }.compilesWithoutError()
     }
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
index 652abe7..f6811fe 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
@@ -26,6 +26,7 @@
 import androidx.room.ext.PagingTypeNames
 import androidx.room.ext.SupportDbTypeNames
 import androidx.room.ext.hasAnnotation
+import androidx.room.ext.requireTypeElement
 import androidx.room.ext.typeName
 import androidx.room.processor.ProcessorErrors.RAW_QUERY_STRING_PARAMETER_REMOVED
 import androidx.room.testing.TestInvocation
@@ -197,7 +198,7 @@
     fun suspendUnit() {
         simpleRun { invocation ->
             val daoElement =
-                invocation.typeElement(RawQuerySuspendUnitDao::class.java.canonicalName!!)
+                invocation.processingEnv.requireTypeElement(RawQuerySuspendUnitDao::class)
             val daoFunctionElement = ElementFilter.methodsIn(daoElement.enclosedElements).first()
             RawQueryMethodProcessor(
                 baseContext = invocation.context,
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
index d8446c5..92b97fd 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.processor.autovalue
 
+import androidx.room.ext.requireTypeElement
 import androidx.room.processor.FieldProcessor
 import androidx.room.processor.PojoProcessor
 import androidx.room.processor.ProcessorErrors
@@ -102,7 +103,7 @@
         )
         simpleRun(classpathFiles = libraryClasspath) { invocation ->
                 PojoProcessor.createFor(context = invocation.context,
-                    element = invocation.typeElement(MY_POJO.toString()),
+                    element = invocation.processingEnv.requireTypeElement(MY_POJO),
                     bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                     parent = null).process()
         }.compilesWithoutError().withWarningCount(0)
@@ -265,7 +266,7 @@
         return simpleRun(*all, classpathFiles = classpathFiles) { invocation ->
             handler.invoke(
                     PojoProcessor.createFor(context = invocation.context,
-                            element = invocation.typeElement(MY_POJO.toString()),
+                            element = invocation.processingEnv.requireTypeElement(MY_POJO),
                             bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
                             parent = null).process(),
                     invocation
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
index 4a14c7b..cbd45b4 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.solver
 
+import androidx.room.ext.requireTypeMirror
 import androidx.room.processor.Context
 import androidx.room.testing.TestInvocation
 import com.squareup.javapoet.ClassName
@@ -176,7 +177,7 @@
             return if (typeKind.isPrimitive) {
                 processingEnv.typeUtils.getPrimitiveType(typeKind)
             } else {
-                processingEnv.elementUtils.getTypeElement(qName).asType()
+                processingEnv.requireTypeMirror(qName!!)
             }
         }
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index d7145df..b5e1854 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -29,6 +29,8 @@
 import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.RxJava3TypeNames
 import androidx.room.ext.T
+import androidx.room.ext.requireTypeElement
+import androidx.room.ext.requireTypeMirror
 import androidx.room.ext.typeName
 import androidx.room.parser.SQLTypeAffinity
 import androidx.room.processor.Context
@@ -88,9 +90,7 @@
             val store = TypeAdapterStore.create(Context(invocation.processingEnv))
             val boolean = invocation
                     .processingEnv
-                    .elementUtils
-                    .getTypeElement("java.lang.Boolean")
-                    .asType()
+                    .requireTypeMirror("java.lang.Boolean")
             val adapter = store.findColumnTypeAdapter(boolean, null)
             assertThat(adapter, notNullValue())
             assertThat(adapter, instanceOf(CompositeAdapter::class.java))
@@ -134,8 +134,7 @@
         singleRun { invocation ->
             val store = TypeAdapterStore.create(Context(invocation.processingEnv),
                     pointTypeConverters(invocation.processingEnv))
-            val pointType = invocation.processingEnv.elementUtils
-                    .getTypeElement("foo.bar.Point").asType()
+            val pointType = invocation.processingEnv.requireTypeMirror("foo.bar.Point")
             val adapter = store.findColumnTypeAdapter(pointType, null)
             assertThat(adapter, notNullValue())
             assertThat(adapter, instanceOf(CompositeAdapter::class.java))
@@ -167,7 +166,7 @@
         singleRun { (processingEnv) ->
             val store = TypeAdapterStore.create(Context(processingEnv),
                     dateTypeConverters(processingEnv))
-            val tDate = processingEnv.elementUtils.getTypeElement("java.util.Date").asType()
+            val tDate = processingEnv.requireTypeMirror("java.util.Date")
             val adapter = store.findCursorValueReader(tDate, SQLTypeAffinity.INTEGER)
             assertThat(adapter, notNullValue())
             assertThat(adapter?.typeMirror(), `is`(tDate))
@@ -235,8 +234,8 @@
     @Test
     fun testMissingRx2Room() {
         simpleRun(jfos = *arrayOf(COMMON.PUBLISHER, COMMON.RX2_FLOWABLE)) { invocation ->
-            val publisherElement = invocation.processingEnv.elementUtils
-                    .getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
+            val publisherElement = invocation.processingEnv
+                    .requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
             assertThat(publisherElement, notNullValue())
             assertThat(
                 RxQueryResultBinderProvider.getAll(invocation.context).any {
@@ -248,8 +247,8 @@
     @Test
     fun testMissingRx3Room() {
         simpleRun(jfos = *arrayOf(COMMON.PUBLISHER, COMMON.RX3_FLOWABLE)) { invocation ->
-            val publisherElement = invocation.processingEnv.elementUtils
-                .getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
+            val publisherElement = invocation.processingEnv
+                .requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
             assertThat(publisherElement, notNullValue())
             assertThat(
                 RxQueryResultBinderProvider.getAll(invocation.context).any {
@@ -266,8 +265,8 @@
         ).forEach { (rxTypeSrc, rxRoomSrc) ->
             simpleRun(jfos = *arrayOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc)) {
                     invocation ->
-                val publisher = invocation.processingEnv.elementUtils
-                    .getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
+                val publisher = invocation.processingEnv
+                    .requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
                 assertThat(publisher, notNullValue())
                 assertThat(
                     RxQueryResultBinderProvider.getAll(invocation.context).any {
@@ -285,9 +284,7 @@
         ).forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
             simpleRun(jfos = *arrayOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc)) {
                 invocation ->
-                val flowable = invocation.processingEnv.elementUtils
-                        .getTypeElement(rxTypeClassName.toString())
-                assertThat(flowable, notNullValue())
+                val flowable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
                 assertThat(
                     RxQueryResultBinderProvider.getAll(invocation.context).any {
                         it.matches(MoreTypes.asDeclared(flowable.asType()))
@@ -304,8 +301,7 @@
         ).forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
             simpleRun(jfos = *arrayOf(rxTypeSrc, rxRoomSrc)) {
                 invocation ->
-                val observable = invocation.processingEnv.elementUtils
-                        .getTypeElement(rxTypeClassName.toString())
+                val observable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
                 assertThat(observable, notNullValue())
                 assertThat(
                     RxQueryResultBinderProvider.getAll(invocation.context).any {
@@ -323,8 +319,7 @@
         ).forEach { (rxTypeSrc, _, rxTypeClassName) ->
             simpleRun(jfos = *arrayOf(rxTypeSrc)) {
                 invocation ->
-                val single = invocation.processingEnv.elementUtils
-                        .getTypeElement(rxTypeClassName.toString())
+                val single = invocation.processingEnv.requireTypeElement(rxTypeClassName)
                 assertThat(single, notNullValue())
                 assertThat(
                     RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
@@ -342,9 +337,7 @@
         ).forEach { (rxTypeSrc, _, rxTypeClassName) ->
             simpleRun(jfos = *arrayOf(rxTypeSrc)) {
                 invocation ->
-                val maybe = invocation.processingEnv.elementUtils
-                        .getTypeElement(rxTypeClassName.toString())
-                assertThat(maybe, notNullValue())
+                val maybe = invocation.processingEnv.requireTypeElement(rxTypeClassName)
                 assertThat(
                     RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
                         it.matches(MoreTypes.asDeclared(maybe.asType()))
@@ -361,9 +354,7 @@
         ).forEach { (rxTypeSrc, _, rxTypeClassName) ->
             simpleRun(jfos = *arrayOf(rxTypeSrc)) {
                 invocation ->
-                val completable = invocation.processingEnv.elementUtils
-                        .getTypeElement(rxTypeClassName.toString())
-                assertThat(completable, notNullValue())
+                val completable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
                 assertThat(
                     RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
                         it.matches(MoreTypes.asDeclared(completable.asType()))
@@ -376,9 +367,8 @@
     fun testFindInsertListenableFuture() {
         simpleRun(jfos = *arrayOf(COMMON.LISTENABLE_FUTURE)) {
                 invocation ->
-            val future = invocation.processingEnv.elementUtils
-                .getTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE.toString())
-            assertThat(future, notNullValue())
+            val future = invocation.processingEnv
+                .requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
             assertThat(GuavaListenableFutureInsertMethodBinderProvider(invocation.context).matches(
                 MoreTypes.asDeclared(future.asType())), `is`(true))
         }.compilesWithoutError()
@@ -388,8 +378,7 @@
     fun testFindDeleteOrUpdateSingle() {
         simpleRun(jfos = *arrayOf(COMMON.RX2_SINGLE)) {
             invocation ->
-            val single = invocation.processingEnv.elementUtils
-                    .getTypeElement(RxJava2TypeNames.SINGLE.toString())
+            val single = invocation.processingEnv.requireTypeElement(RxJava2TypeNames.SINGLE)
             assertThat(single, notNullValue())
             assertThat(
                 RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
@@ -402,8 +391,7 @@
     fun testFindDeleteOrUpdateMaybe() {
         simpleRun(jfos = *arrayOf(COMMON.RX2_MAYBE)) {
             invocation ->
-            val maybe = invocation.processingEnv.elementUtils
-                    .getTypeElement(RxJava2TypeNames.MAYBE.toString())
+            val maybe = invocation.processingEnv.requireTypeElement(RxJava2TypeNames.MAYBE)
             assertThat(maybe, notNullValue())
             assertThat(
                 RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
@@ -416,8 +404,8 @@
     fun testFindDeleteOrUpdateCompletable() {
         simpleRun(jfos = *arrayOf(COMMON.RX2_COMPLETABLE)) {
             invocation ->
-            val completable = invocation.processingEnv.elementUtils
-                    .getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())
+            val completable = invocation.processingEnv
+                    .requireTypeElement(RxJava2TypeNames.COMPLETABLE)
             assertThat(completable, notNullValue())
             assertThat(
                 RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
@@ -430,8 +418,8 @@
     fun testFindDeleteOrUpdateListenableFuture() {
         simpleRun(jfos = *arrayOf(COMMON.LISTENABLE_FUTURE)) {
                 invocation ->
-            val future = invocation.processingEnv.elementUtils
-                .getTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE.toString())
+            val future = invocation.processingEnv
+                .requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
             assertThat(future, notNullValue())
             assertThat(GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(invocation.context)
                 .matches(MoreTypes.asDeclared(future.asType())), `is`(true))
@@ -442,8 +430,8 @@
     fun testFindLiveData() {
         simpleRun(jfos = *arrayOf(COMMON.COMPUTABLE_LIVE_DATA, COMMON.LIVE_DATA)) {
             invocation ->
-            val liveData = invocation.processingEnv.elementUtils
-                    .getTypeElement(LifecyclesTypeNames.LIVE_DATA.toString())
+            val liveData = invocation.processingEnv
+                    .requireTypeElement(LifecyclesTypeNames.LIVE_DATA)
             assertThat(liveData, notNullValue())
             assertThat(LiveDataQueryResultBinderProvider(invocation.context).matches(
                     MoreTypes.asDeclared(liveData.asType())), `is`(true))
@@ -453,11 +441,9 @@
     @Test
     fun findPagingSourceIntKey() {
         simpleRun { invocation ->
-            val pagingSourceElement = invocation.processingEnv.elementUtils
-                .getTypeElement(PagingSource::class.java.canonicalName)
-            val intType = invocation.processingEnv.elementUtils
-                .getTypeElement(Integer::class.java.canonicalName)
-                .asType()
+            val pagingSourceElement = invocation.processingEnv
+                .requireTypeElement(PagingSource::class)
+            val intType = invocation.processingEnv.requireTypeMirror(Integer::class)
             val pagingSourceIntIntType = invocation.processingEnv.typeUtils
                 .getDeclaredType(pagingSourceElement, intType, intType)
 
@@ -470,11 +456,9 @@
     @Test
     fun findPagingSourceStringKey() {
         simpleRun { invocation ->
-            val pagingSourceElement = invocation.processingEnv.elementUtils
-                .getTypeElement(PagingSource::class.java.canonicalName)
-            val stringType = invocation.processingEnv.elementUtils
-                .getTypeElement(String::class.java.canonicalName)
-                .asType()
+            val pagingSourceElement = invocation.processingEnv
+                .requireTypeElement(PagingSource::class)
+            val stringType = invocation.processingEnv.requireTypeMirror(String::class)
             val pagingSourceIntIntType = invocation.processingEnv.typeUtils
                 .getDeclaredType(pagingSourceElement, stringType, stringType)
 
@@ -488,8 +472,7 @@
     fun findDataSource() {
         simpleRun {
             invocation ->
-            val dataSource = invocation.processingEnv.elementUtils
-                    .getTypeElement(DataSource::class.java.canonicalName)
+            val dataSource = invocation.processingEnv.requireTypeElement(DataSource::class)
             assertThat(dataSource, notNullValue())
             assertThat(DataSourceQueryResultBinderProvider(invocation.context).matches(
                     MoreTypes.asDeclared(dataSource.asType())), `is`(true))
@@ -501,8 +484,8 @@
         simpleRun {
             invocation ->
             @Suppress("DEPRECATION")
-            val dataSource = invocation.processingEnv.elementUtils
-                    .getTypeElement(androidx.paging.PositionalDataSource::class.java.canonicalName)
+            val dataSource = invocation.processingEnv
+                .requireTypeElement(androidx.paging.PositionalDataSource::class)
             assertThat(dataSource, notNullValue())
             assertThat(DataSourceQueryResultBinderProvider(invocation.context).matches(
                     MoreTypes.asDeclared(dataSource.asType())), `is`(true))
@@ -513,8 +496,8 @@
     fun findDataSourceFactory() {
         simpleRun(jfos = *arrayOf(COMMON.DATA_SOURCE_FACTORY)) {
             invocation ->
-            val pagedListProvider = invocation.processingEnv.elementUtils
-                    .getTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY.toString())
+            val pagedListProvider = invocation.processingEnv
+                    .requireTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY)
             assertThat(pagedListProvider, notNullValue())
             assertThat(DataSourceFactoryQueryResultBinderProvider(invocation.context).matches(
                     MoreTypes.asDeclared(pagedListProvider.asType())), `is`(true))
@@ -522,12 +505,9 @@
     }
 
     private fun createIntListToStringBinders(invocation: TestInvocation): List<TypeConverter> {
-        val intType = invocation.processingEnv.elementUtils
-                .getTypeElement(Integer::class.java.canonicalName)
-                .asType()
-        val listType = invocation.processingEnv.elementUtils
-                .getTypeElement(java.util.List::class.java.canonicalName)
-        val listOfInts = invocation.processingEnv.typeUtils.getDeclaredType(listType, intType)
+        val intType = invocation.processingEnv.requireTypeMirror(Integer::class)
+        val listElement = invocation.processingEnv.requireTypeElement(java.util.List::class)
+        val listOfInts = invocation.processingEnv.typeUtils.getDeclaredType(listElement, intType)
 
         val intListConverter = object : TypeConverter(listOfInts,
                 invocation.context.COMMON_TYPES.STRING) {
@@ -598,7 +578,7 @@
     }
 
     fun pointTypeConverters(env: ProcessingEnvironment): List<TypeConverter> {
-        val tPoint = env.elementUtils.getTypeElement("foo.bar.Point").asType()
+        val tPoint = env.requireTypeMirror("foo.bar.Point")
         val tBoolean = env.typeUtils.getPrimitiveType(TypeKind.BOOLEAN)
         return listOf(
                 object : TypeConverter(tPoint, tBoolean) {
@@ -628,8 +608,8 @@
     }
 
     fun dateTypeConverters(env: ProcessingEnvironment): List<TypeConverter> {
-        val tDate = env.elementUtils.getTypeElement("java.util.Date").asType()
-        val tLong = env.elementUtils.getTypeElement("java.lang.Long").asType()
+        val tDate = env.requireTypeMirror("java.util.Date")
+        val tLong = env.requireTypeMirror("java.lang.Long")
         return listOf(
                 object : TypeConverter(tDate, tLong) {
                     override fun convert(
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
index 8a56a8b..8596df1 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
@@ -17,7 +17,8 @@
 package androidx.room.solver
 
 import androidx.room.ext.getAllFieldsIncludingPrivateSupers
-import androidx.room.ext.isAssignableWithoutVariance
+import androidx.room.ext.isAssignableFromWithoutVariance
+import androidx.room.ext.requireTypeElement
 import androidx.room.testing.TestInvocation
 import com.google.testing.compile.JavaFileObjects
 import org.hamcrest.CoreMatchers.`is`
@@ -51,11 +52,11 @@
     @Test
     fun basic() {
         runTest {
-            val testObject = typeElement("foo.bar.MyObject")
+            val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
             val string = testObject.getField(processingEnv, "mString")
             val integer = testObject.getField(processingEnv, "mInteger")
-            assertThat(typeUtils.isAssignableWithoutVariance(string.asType(),
-                    integer.asType()),
+            assertThat( integer.asType()
+                .isAssignableFromWithoutVariance(typeUtils, string.asType()),
                     `is`(false))
         }
     }
@@ -63,17 +64,11 @@
     @Test
     fun generics() {
         runTest {
-            val testObject = typeElement("foo.bar.MyObject")
+            val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
             val set = testObject.getField(processingEnv, "mSet").asType()
             val hashSet = testObject.getField(processingEnv, "mHashSet").asType()
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = set,
-                    to = hashSet
-            ), `is`(false))
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = hashSet,
-                    to = set
-            ), `is`(true))
+            assertThat(hashSet.isAssignableFromWithoutVariance(typeUtils, set), `is`(false))
+            assertThat(set.isAssignableFromWithoutVariance(typeUtils, hashSet), `is`(true))
         }
     }
 
@@ -86,34 +81,22 @@
          *                       // to accept it
          */
         runTest {
-            val testObject = typeElement("foo.bar.MyObject")
+            val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
             val set = testObject.getField(processingEnv, "mSet").asType()
             val varianceSet = testObject.getField(processingEnv, "mVarianceSet").asType()
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = set,
-                    to = varianceSet
-            ), `is`(true))
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = varianceSet,
-                    to = set
-            ), `is`(true))
+            assertThat(varianceSet.isAssignableFromWithoutVariance(typeUtils, set), `is`(true))
+            assertThat(set.isAssignableFromWithoutVariance(typeUtils, varianceSet), `is`(true))
         }
     }
 
     @Test
     fun unboundedVariance() {
         runTest {
-            val testObject = typeElement("foo.bar.MyObject")
+            val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
             val unbounded = testObject.getField(processingEnv, "mUnboundedMap").asType()
             val objectMap = testObject.getField(processingEnv, "mStringMap").asType()
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = unbounded,
-                    to = objectMap
-            ), `is`(false))
-            assertThat(typeUtils.isAssignableWithoutVariance(
-                    from = objectMap,
-                    to = unbounded
-            ), `is`(true))
+            assertThat(objectMap.isAssignableFromWithoutVariance(typeUtils, unbounded), `is`(false))
+            assertThat(unbounded.isAssignableFromWithoutVariance(typeUtils, objectMap), `is`(true))
         }
     }
 
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/TestInvocation.kt b/room/compiler/src/test/kotlin/androidx/room/testing/TestInvocation.kt
index aeb9346..79acd1d 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/TestInvocation.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/TestInvocation.kt
@@ -28,9 +28,5 @@
 ) {
     val context = Context(processingEnv)
 
-    fun typeElement(qName: String): TypeElement {
-        return processingEnv.elementUtils.getTypeElement(qName)
-    }
-
     val typeUtils by lazy { processingEnv.typeUtils }
 }
diff --git a/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt b/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
index 0c5ab32..5a2fb8b 100644
--- a/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.verifier
 
+import androidx.room.ext.requireTypeElement
 import androidx.room.parser.Collate
 import androidx.room.parser.SQLTypeAffinity
 import androidx.room.parser.SqlParser
@@ -289,7 +290,7 @@
         tableName: String,
         vararg fields: Field
     ): Entity {
-        val element = invocation.typeElement("Dummy")
+        val element = invocation.processingEnv.requireTypeElement("Dummy")
         return Entity(
             element = element,
             tableName = tableName,
diff --git a/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
index 7d247b5..8071098 100644
--- a/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
@@ -18,6 +18,7 @@
 
 import COMMON
 import androidx.room.ext.RoomTypeNames
+import androidx.room.ext.requireTypeElement
 import androidx.room.processor.DaoProcessor
 import androidx.room.testing.TestProcessor
 import com.google.auto.common.MoreElements
@@ -90,14 +91,9 @@
                                     .getElementsAnnotatedWith(
                                             androidx.room.Database::class.java)
                                     .firstOrNull()
-                                    ?: invocation.context.processingEnv.elementUtils
-                                        .getTypeElement(RoomTypeNames.ROOM_DB.toString())
-                            val dbType = if (db != null) {
-                                db.asType()
-                            } else {
-                                invocation.context.processingEnv.elementUtils
-                                    .getTypeElement(RoomTypeNames.ROOM_DB.toString()).asType()
-                            }.let { MoreTypes.asDeclared(it) }
+                                    ?: invocation.context.processingEnv
+                                        .requireTypeElement(RoomTypeNames.ROOM_DB)
+                            val dbType = MoreTypes.asDeclared(db.asType())
                             val parser = DaoProcessor(
                                     baseContext = invocation.context,
                                     element = MoreElements.asType(dao),
diff --git a/samples/Support7Demos/src/main/AndroidManifest.xml b/samples/Support7Demos/src/main/AndroidManifest.xml
index cedba3f..cad3c93 100644
--- a/samples/Support7Demos/src/main/AndroidManifest.xml
+++ b/samples/Support7Demos/src/main/AndroidManifest.xml
@@ -117,6 +117,8 @@
             </intent-filter>
         </service>
 
+        <receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
+
         <!-- GridLayout Support Samples -->
 
         <activity android:name=".view.GridLayout1"
@@ -753,8 +755,6 @@
             </intent-filter>
         </activity>
 
-        <meta-data android:name="androidx.mediarouter.FEATURE"
-            android:value="seamless_transfer" />
     </application>
 
 </manifest>
diff --git a/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
index a8f5d9f..486d160 100644
--- a/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
+++ b/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
@@ -65,6 +65,7 @@
 import androidx.mediarouter.media.MediaRouter.Callback;
 import androidx.mediarouter.media.MediaRouter.ProviderInfo;
 import androidx.mediarouter.media.MediaRouter.RouteInfo;
+import androidx.mediarouter.media.MediaRouterParams;
 
 import com.example.android.supportv7.R;
 
@@ -218,6 +219,11 @@
         // Get the media router service.
         mMediaRouter = MediaRouter.getInstance(this);
 
+        MediaRouterParams params = new MediaRouterParams();
+        params.setDialogType(MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP);
+        params.setOutputSwitcherEnabled(true); // Output switcher will be shown from Android R+.
+        mMediaRouter.setRouterParams(params);
+
         // Create a route selector for the type of routes that we care about.
         mSelector = new MediaRouteSelector.Builder()
                 .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
@@ -508,7 +514,6 @@
         MediaRouteActionProvider mediaRouteActionProvider =
                 (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
         mediaRouteActionProvider.setRouteSelector(mSelector);
-        mediaRouteActionProvider.enableDynamicGroup();
         mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() {
             @Override
             public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() {
diff --git a/ui/README.md b/ui/README.md
index 6d57d20..72534f4 100644
--- a/ui/README.md
+++ b/ui/README.md
@@ -28,13 +28,7 @@
 
 Run the `demos` app to see examples of individual components.
 
-A sample implementation of the [Material Rally app](https://material.io/design/material-studies/rally.html) is under `material/integration-tests/material-studies`.
-
-To build the Material Rally app via the command line run:
-
-    cd path/to/checkout/frameworks/support/ui/
-    ./gradlew :ui-material:integration-tests:ui-material-studies:assembleDebug
-
+A sample implementation of the [Material Rally app](https://material.io/design/material-studies/rally.html) is under `material/integration-tests/material-studies`. This can be viewed from inside the `demos` app, under the 'Material Studies' section.
 
 ## Structure
 Library code for Jetpack Compose lives under the `frameworks/support/ui` directory. Additionally, sample code can be found within each module in the `integration-tests` subdirectories and the compiler and runtime code can be found in `frameworks/support/compose`.
diff --git a/ui/integration-tests/OWNERS b/ui/integration-tests/OWNERS
index 7885869..2047fdcd 100644
--- a/ui/integration-tests/OWNERS
+++ b/ui/integration-tests/OWNERS
@@ -4,5 +4,5 @@
 qqd@google.com
 siyamed@google.com
 
-# For ui-core and ui-foundation benchmarks
+# For ui-core and foundation benchmarks
 malkov@google.com
diff --git a/ui/integration-tests/benchmark/build.gradle b/ui/integration-tests/benchmark/build.gradle
index 40db4f5..2689f07 100644
--- a/ui/integration-tests/benchmark/build.gradle
+++ b/ui/integration-tests/benchmark/build.gradle
@@ -44,7 +44,7 @@
 
     androidTestImplementation project(":ui:ui-core")
     androidTestImplementation project(":ui:ui-layout")
-    androidTestImplementation project(":ui:ui-material")
+    androidTestImplementation project(":compose:material:material")
     androidTestImplementation project(":ui:ui-test")
     androidTestImplementation project(":compose:compose-runtime")
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/ui/integration-tests/build.gradle b/ui/integration-tests/build.gradle
index 4ec4ee6..f84edad 100644
--- a/ui/integration-tests/build.gradle
+++ b/ui/integration-tests/build.gradle
@@ -40,9 +40,9 @@
 
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
     implementation project(":ui:ui-test")
 }
 
diff --git a/ui/integration-tests/demos/build.gradle b/ui/integration-tests/demos/build.gradle
index 57598cf..d0f27a2 100644
--- a/ui/integration-tests/demos/build.gradle
+++ b/ui/integration-tests/demos/build.gradle
@@ -14,11 +14,11 @@
 
     implementation project(":ui:ui-android-view:integration-tests:ui-android-view-demos")
     implementation project(":ui:ui-animation:integration-tests:ui-animation-demos")
-    implementation project(":ui:ui-foundation:integration-tests:ui-foundation-demos")
+    implementation project(":compose:foundation:foundation:integration-tests:foundation-demos")
     implementation project(":ui:ui-core:integration-tests:ui-core-demos")
     implementation project(":ui:ui-layout:integration-tests:ui-layout-demos")
-    implementation project(":ui:ui-material:integration-tests:ui-material-demos")
-    implementation project(":ui:ui-material:integration-tests:ui-material-studies")
+    implementation project(":compose:material:material:integration-tests:material-demos")
+    implementation project(":compose:material:material:integration-tests:material-studies")
     implementation project(":ui:ui-text:integration-tests:ui-text-compose-demos")
 
     implementation(KOTLIN_REFLECT)
@@ -29,8 +29,8 @@
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text")
-    implementation project(":ui:ui-foundation")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:foundation:foundation")
+    implementation project(":compose:material:material")
     implementation project(":ui:integration-tests:demos:common")
 
     implementation "androidx.preference:preference-ktx:1.1.0"
@@ -40,11 +40,11 @@
     // TODO: presumably shouldn't need to specify these again? figure out why this is needed.
     androidTestImplementation project(":ui:ui-android-view:integration-tests:ui-android-view-demos")
     androidTestImplementation project(":ui:ui-animation:integration-tests:ui-animation-demos")
-    androidTestImplementation project(":ui:ui-foundation:integration-tests:ui-foundation-demos")
+    androidTestImplementation project(":compose:foundation:foundation:integration-tests:foundation-demos")
     androidTestImplementation project(":ui:ui-core:integration-tests:ui-core-demos")
     androidTestImplementation project(":ui:ui-layout:integration-tests:ui-layout-demos")
-    androidTestImplementation project(":ui:ui-material:integration-tests:ui-material-demos")
-    androidTestImplementation project(":ui:ui-material:integration-tests:ui-material-studies")
+    androidTestImplementation project(":compose:material:material:integration-tests:material-demos")
+    androidTestImplementation project(":compose:material:material:integration-tests:material-studies")
     androidTestImplementation project(":ui:ui-text:integration-tests:ui-text-compose-demos")
 
     androidTestImplementation(ANDROIDX_TEST_RULES)
diff --git a/ui/settings.gradle b/ui/settings.gradle
index 5b451f7..9c2307e 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -77,9 +77,10 @@
     includeProject(":ui:ui-desktop:android-emu", "ui-desktop/android-emu")
     includeProject(":ui:ui-desktop:samples", "ui-desktop/samples")
 }
-includeProject(":ui:ui-foundation", "ui-foundation")
-includeProject(":ui:ui-foundation:integration-tests:ui-foundation-demos", "ui-foundation/integration-tests/foundation-demos")
-includeProject(":ui:ui-foundation:samples", "ui-foundation/samples")
+includeProject(":compose:foundation", "../compose/foundation")
+includeProject(":compose:foundation:foundation", "ui-foundation")
+includeProject(":compose:foundation:foundation:integration-tests:foundation-demos", "ui-foundation/integration-tests/foundation-demos")
+includeProject(":compose:foundation:foundation:samples", "ui-foundation/samples")
 includeProject(":ui:ui-internal-lint-checks", "ui-internal-lint-checks")
 includeProject(":ui:ui-geometry", "ui-geometry")
 includeProject(":ui:ui-graphics", "ui-graphics")
@@ -87,14 +88,15 @@
 includeProject(":ui:ui-layout", "ui-layout")
 includeProject(":ui:ui-layout:integration-tests:ui-layout-demos", "ui-layout/integration-tests/layout-demos")
 includeProject(":ui:ui-layout:samples", "ui-layout/samples")
-includeProject(":ui:ui-material", "ui-material")
-includeProject(":ui:ui-material:integration-tests:ui-material-demos", "ui-material/integration-tests/material-demos")
-includeProject(":ui:ui-material:integration-tests:ui-material-studies", "ui-material/integration-tests/material-studies")
-includeProject(":ui:ui-material:samples", "ui-material/samples")
-includeProject(":ui:ui-material-icons-core", "ui-material/icons/core")
-includeProject(":ui:ui-material-icons-core:samples", "ui-material/icons/core/samples")
-includeProject(":ui:ui-material-icons-extended", "ui-material/icons/extended")
-includeProject(":ui:ui-material:icons:generator", "ui-material/icons/generator")
+includeProject(":compose:material", "../compose/material")
+includeProject(":compose:material:material", "ui-material")
+includeProject(":compose:material:material:integration-tests:material-demos", "ui-material/integration-tests/material-demos")
+includeProject(":compose:material:material:integration-tests:material-studies", "ui-material/integration-tests/material-studies")
+includeProject(":compose:material:material:samples", "ui-material/samples")
+includeProject(":compose:material:material-icons-core", "ui-material/icons/core")
+includeProject(":compose:material:material-icons-core:samples", "ui-material/icons/core/samples")
+includeProject(":compose:material:material-icons-extended", "ui-material/icons/extended")
+includeProject(":compose:material:material:icons:generator", "ui-material/icons/generator")
 includeProject(":ui:ui-test", "ui-test")
 includeProject(":ui:ui-test-font", "ui-test-font")
 includeProject(":ui:ui-text", "ui-text")
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/build.gradle b/ui/ui-android-view/integration-tests/android-view-demos/build.gradle
index e87fcb9..15b72c7 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/build.gradle
+++ b/ui/ui-android-view/integration-tests/android-view-demos/build.gradle
@@ -35,7 +35,7 @@
     implementation project(":ui:ui-android-view")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
 }
 
 android {
diff --git a/ui/ui-android-view/samples/build.gradle b/ui/ui-android-view/samples/build.gradle
index e6b64d4..c4646c9 100644
--- a/ui/ui-android-view/samples/build.gradle
+++ b/ui/ui-android-view/samples/build.gradle
@@ -34,7 +34,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-android-view")
 }
diff --git a/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
index 079111f..0816cb2 100644
--- a/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
@@ -32,23 +32,22 @@
 @InternalAnimationApi
 class SeekableAnimation<T>(
     val def: TransitionDefinition<T>,
-    fromState: T,
-    toState: T
+    val fromState: T,
+    val toState: T
 ) {
     private val currentValues: MutableMap<PropKey<Any, AnimationVector>, Any> = mutableMapOf()
     private val currentAnimWrappers: MutableMap<PropKey<Any, AnimationVector>,
             Animation<Any, AnimationVector>> = mutableMapOf()
-    private val toState = def.states[toState]!!
-    private val fromState = def.states[fromState]!!
 
     init {
-        currentValues.putAll(this.fromState.props)
+        val to = def.states[toState]!!
+        val from = def.states[fromState]!!
+        currentValues.putAll(from.props)
         val transSpec: TransitionSpec<T> = def.getSpec(fromState, toState)
         // Initialize currentAnimWrappers
-        for ((prop, _) in this.toState.props) {
+        for ((prop, _) in to.props) {
             currentAnimWrappers[prop] = prop.createAnimationWrapper(
-                transSpec.getAnimationForProp(prop), this.fromState[prop], null,
-                this.toState[prop]
+                transSpec.getAnimationForProp(prop), from[prop], null, to[prop]
             )
         }
     }
@@ -68,9 +67,9 @@
      */
     fun getAnimValuesAt(playTime: Long): Map<PropKey<Any, AnimationVector>, Any> {
         if (playTime <= 0) {
-            currentValues.putAll(fromState.props)
+            currentValues.putAll(def.states[fromState]!!.props)
         } else if (playTime >= duration) {
-            currentValues.putAll(toState.props)
+            currentValues.putAll(def.states[toState]!!.props)
         } else {
             for ((prop, animation) in currentAnimWrappers) {
                 currentValues[prop] = animation.getValue(playTime)
diff --git a/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
index bc3bdde..1f23d77 100644
--- a/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
@@ -75,10 +75,12 @@
     inner class TransitionAnimationClockObserver : AnimationClockObserver {
         // This API is intended for tools' use only. Hence the @InternalAnimationApi.
         val animation: TransitionAnimation<T> = this@TransitionAnimation
+
         override fun onAnimationFrame(frameTimeMillis: Long) {
             doAnimationFrame(frameTimeMillis)
         }
     }
+
     private val animationClockObserver: AnimationClockObserver = TransitionAnimationClockObserver()
 
     // TODO("Create a more efficient code path for default only transition def")
@@ -159,6 +161,59 @@
     }
 
     /**
+     * This indicates whether animation assumes time stamps increase monotonically. If false,
+     * animation will anticipate that the time may go backwards, therefore it won't ever finish,
+     * until it's set to true again.
+     * @suppress
+     */
+    @InternalAnimationApi
+    var monotonic: Boolean = true
+        set(value) {
+            if (field == value) {
+                return
+            }
+            field = value
+            // Changing from false to true
+            if (value && isRunning) {
+                // Pump in another frame to properly finish
+                doAnimationFrame(lastFrameTime)
+            }
+        }
+
+    /**
+     * This immediately and violently snaps the animation to the new state, regardless whether
+     * there's an on-going animation. This will also put the animation in an finished state,
+     * effectively unsubscribing the animation from the clock.
+     *
+     * @param toState the state that animation will be snapped to
+     *
+     * @suppress
+     */
+    @InternalAnimationApi
+    fun snapToState(toState: T) {
+        val stateChanged = toState == fromState.name
+
+        // Snap all values to end value
+        val newState = def.states[toState]!!
+        for (prop in newState.props.keys) {
+            currentState[prop] = newState[prop]
+        }
+        startVelocityMap.clear()
+
+        if (isRunning) {
+            endAnimation()
+            currentAnimWrappers.clear()
+            fromState = newState
+            this.toState = newState
+            pendingState = null
+        }
+
+        if (stateChanged) {
+            onStateChangeFinished?.invoke(toState)
+        }
+    }
+
+    /**
      * Gets the value of a property with a given property key.
      *
      * @param propKey Property key (defined in [TransitionDefinition]) for a specific property
@@ -185,19 +240,22 @@
         }
 
         val playTime = getPlayTime()
+        var finished = true
         for ((prop, animation) in currentAnimWrappers) {
-            currentState[prop] = animation.getValue(playTime)
-        }
-
-        // Prune the finished animations
-        currentAnimWrappers.entries.removeAll {
-            it.value.isFinished(playTime)
+            if (!animation.isFinished(playTime)) {
+                currentState[prop] = animation.getValue(playTime)
+                finished = false
+            } else {
+                currentState[prop] = toState[prop]
+            }
         }
 
         onUpdate?.invoke()
 
-        // call end animation when all animations end
-        if (currentAnimWrappers.isEmpty()) {
+        // When all the sub-animations have finished, we'll only end the transition or move on to
+        // the pending state when the transition is monotonic, as we know time won't go backward.
+        // Otherwise, we'll stay subscribed to the animation clock indefinitely.
+        if (finished && monotonic) {
             // All animations have finished. Snap all values to end value
             for (prop in toState.props.keys) {
                 currentState[prop] = toState[prop]
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
index 5d83d77..cc38b0b 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
@@ -17,9 +17,12 @@
 package androidx.animation
 
 import junit.framework.TestCase.assertEquals
+import junit.framework.TestCase.assertFalse
+import junit.framework.TestCase.assertTrue
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import java.lang.Float.min
 
 @RunWith(JUnit4::class)
 class TransitionAnimationTest {
@@ -69,6 +72,64 @@
         clock.clockTimeMillis += 100000
         assertEquals(AnimState.B, lastState)
     }
+
+    @Test
+    @OptIn(InternalAnimationApi::class)
+    fun testNonMonotonicTransition() {
+        var finished = false
+        val clock = ManualAnimationClock(0)
+        val anim = TransitionAnimation(def2, clock, AnimState.A)
+        anim.monotonic = false
+        anim.onStateChangeFinished = {
+            finished = true
+        }
+        anim.toState(AnimState.B)
+
+        listOf(0, 200, 499, 500, 600, 300, 100, 0, 505).forEach { timeStamp ->
+            clock.clockTimeMillis = timeStamp.toLong()
+            assertEquals(min(timeStamp.toFloat(), 200f), anim[prop1])
+            assertEquals(min(timeStamp.toFloat(), 500f), anim[prop2])
+        }
+        assertFalse(finished)
+
+        // Changing monotonic to true should result in another frame being pumped with the last
+        // time stamp.
+        anim.monotonic = true
+        assertTrue(finished)
+    }
+
+    @Test
+    @OptIn(InternalAnimationApi::class)
+    fun testSnapToState() {
+        val clock = ManualAnimationClock(0)
+        val anim = TransitionAnimation(def2, clock, AnimState.A)
+
+        // Animate A -> B
+        anim.toState(AnimState.B)
+        clock.clockTimeMillis = 100
+        assertEquals(100f, anim[prop1])
+        assertEquals(100f, anim[prop2])
+
+        // Snap to end state
+        anim.snapToState(AnimState.B)
+        assertEquals(200f, anim[prop1])
+        assertEquals(500f, anim[prop2])
+        assertFalse(anim.isRunning)
+
+        clock.clockTimeMillis = 0
+        // Animate B->A
+        anim.toState(AnimState.A)
+        clock.clockTimeMillis = 250
+        assertEquals(0f, anim[prop1])
+        assertEquals(250f, anim[prop2])
+
+        assertTrue(anim.isRunning)
+        // Snap to start state
+        anim.snapToState(AnimState.B)
+        assertEquals(200f, anim[prop1])
+        assertEquals(500f, anim[prop2])
+        assertFalse(anim.isRunning)
+    }
 }
 
 private enum class AnimState {
@@ -93,4 +154,20 @@
         this[prop1] = 1000f
         this[prop2] = -250f
     }
+}
+
+private val def2 = transitionDefinition {
+    state(AnimState.A) {
+        this[prop1] = 0f
+        this[prop2] = 0f
+    }
+    state(AnimState.B) {
+        this[prop1] = 200f
+        this[prop2] = 500f
+    }
+
+    transition {
+        prop1 using TweenSpec(durationMillis = 200, easing = LinearEasing)
+        prop2 using TweenSpec(durationMillis = 500, easing = LinearEasing)
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-animation/build.gradle b/ui/ui-animation/build.gradle
index 15c609a..44b0ce5 100644
--- a/ui/ui-animation/build.gradle
+++ b/ui/ui-animation/build.gradle
@@ -51,7 +51,7 @@
     androidTestImplementation(ANDROIDX_TEST_RULES)
     androidTestImplementation(ANDROIDX_TEST_RUNNER)
     androidTestImplementation(JUNIT)
-    androidTestImplementation project(":ui:ui-foundation")
+    androidTestImplementation project(":compose:foundation:foundation")
     androidTestImplementation project(":ui:ui-test")
 }
 
diff --git a/ui/ui-animation/integration-tests/animation-demos/build.gradle b/ui/ui-animation/integration-tests/animation-demos/build.gradle
index ec2fa00..62072cb 100644
--- a/ui/ui-animation/integration-tests/animation-demos/build.gradle
+++ b/ui/ui-animation/integration-tests/animation-demos/build.gradle
@@ -20,7 +20,7 @@
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text-core")
     implementation project(':ui:ui-animation')
-    implementation project(':ui:ui-foundation')
+    implementation project(':compose:foundation:foundation')
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/ui/ui-animation/samples/build.gradle b/ui/ui-animation/samples/build.gradle
index c14dfa7..5fd19de 100644
--- a/ui/ui-animation/samples/build.gradle
+++ b/ui/ui-animation/samples/build.gradle
@@ -35,7 +35,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-animation")
     implementation project(":ui:ui-text-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
 }
 
 android {
diff --git a/ui/ui-core/build.gradle b/ui/ui-core/build.gradle
index 67d44ad..df2696a 100644
--- a/ui/ui-core/build.gradle
+++ b/ui/ui-core/build.gradle
@@ -91,7 +91,7 @@
             implementation project(":ui:ui-test")
             implementation project(":ui:ui-test-font")
             implementation project(":ui:ui-layout")
-            implementation project(":ui:ui-foundation")
+            implementation project(":compose:foundation:foundation")
         }
     }
 }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/build.gradle b/ui/ui-core/integration-tests/ui-core-demos/build.gradle
index b6b625c..e1e08e5 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/build.gradle
+++ b/ui/ui-core/integration-tests/ui-core-demos/build.gradle
@@ -20,8 +20,8 @@
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-animation")
-    implementation project(":ui:ui-foundation")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:foundation:foundation")
+    implementation project(":compose:material:material")
     implementation project(":ui:ui-livedata")
 }
 
diff --git a/ui/ui-core/samples/build.gradle b/ui/ui-core/samples/build.gradle
index 698232a..ac6e965 100644
--- a/ui/ui-core/samples/build.gradle
+++ b/ui/ui-core/samples/build.gradle
@@ -35,7 +35,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
 }
 
 android {
diff --git a/ui/ui-desktop/build.gradle b/ui/ui-desktop/build.gradle
index 8e14a18..0bddb3d 100644
--- a/ui/ui-desktop/build.gradle
+++ b/ui/ui-desktop/build.gradle
@@ -131,28 +131,28 @@
 }
 
 def uiComponents = [
-        "ui-android-view",
-        "ui-animation",
-        "ui-animation-core",
-        "ui-core",
-        "ui-foundation",
-        "ui-geometry",
-        "ui-graphics",
-        "ui-layout",
-        "ui-livedata",
-        "ui-material",
-        "ui-saved-instance-state",
-        "ui-text",
-        "ui-text-android",
-        "ui-text-core",
-        "ui-unit",
-        "ui-util"
+        ":ui:ui-android-view",
+        ":ui:ui-animation",
+        ":ui:ui-animation-core",
+        ":ui:ui-core",
+        ":compose:foundation:foundation",
+        ":ui:ui-geometry",
+        ":ui:ui-graphics",
+        ":ui:ui-layout",
+        ":ui:ui-livedata",
+        ":ui:ui-saved-instance-state",
+        ":ui:ui-text",
+        ":ui:ui-text-android",
+        ":ui:ui-text-core",
+        ":ui:ui-unit",
+        ":ui:ui-util",
+        ":compose:material:material"
 ]
 
-def androidxComponents = [
-        "core:core",
-        "lifecycle:lifecycle-runtime"
-]
+// Returns the artifact name (project name) from a project path
+static String uiComponentArtifactName(String component) {
+    return component.tokenize(':').last()
+}
 
 void makeLinkOrCopy(String from, String to) {
     def fromPath = Paths.get(from)
@@ -237,10 +237,11 @@
     inputs.files(project.provider {
         def result = []
         uiComponents.each { component ->
-            def depProject = project(":ui:" + component)
+            def depProject = project(component)
             def task = depProject.tasks.named("assemble").get()
             def srcJar = findInDeps(task, { absolutePath ->
-                absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+                def componentPath = component.replaceAll(":", "/")
+                absolutePath.endsWith("classes.jar") && absolutePath.contains(componentPath)
             })
             result.add(file(srcJar))
         }
@@ -268,12 +269,7 @@
     outputs.files(project.provider {
         def result = [fileTree(dir: composeClassDir, include: [])]
         uiComponents.each { component ->
-            def depProject = project(":ui:" + component)
-            def task = depProject.tasks.named("assemble").get()
-            def srcJar = findInDeps(task, { absolutePath ->
-                absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
-            })
-            result.add(file(composeClassDir + component + ".jar"))
+            result.add(file(composeClassDir + uiComponentArtifactName(component) + ".jar"))
         }
         configurations.ui_components.getIncoming().artifactView(
                 { config ->
@@ -291,15 +287,16 @@
         // Find all JAR files matching components.
         file(composeClassDir).mkdir()
         uiComponents.each { component ->
-            def depProject = project(":ui:" + component)
+            def depProject = project(component)
             def task = depProject.tasks.named("assemble").get()
             def srcJar = findInDeps(task, { absolutePath ->
-                absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+                def componentPath = component.replaceAll(":", "/")
+                absolutePath.endsWith("classes.jar") && absolutePath.contains(componentPath)
             })
             if (srcJar == null) {
                 throw new Error("cannot find classes.jar in "+ task)
             } else {
-                def destJar = composeClassDir + component + ".jar"
+                def destJar = composeClassDir + uiComponentArtifactName(component) + ".jar"
                 makeLinkOrCopy(srcJar, destJar)
             }
         }
@@ -321,7 +318,7 @@
 
 extractJars.configure {
     uiComponents.each { component ->
-        extractJars.dependsOn(":ui:" + component + ":assemble")
+        extractJars.dependsOn(component + ":assemble")
     }
 }
 
diff --git a/ui/ui-foundation/build.gradle b/ui/ui-foundation/build.gradle
index 46e9054..6e77427 100644
--- a/ui/ui-foundation/build.gradle
+++ b/ui/ui-foundation/build.gradle
@@ -64,10 +64,10 @@
 }
 
 androidx {
-    name = "Compose Foundation Ui"
+    name = "Compose Foundation"
     publish = Publish.SNAPSHOT_AND_RELEASE
     mavenVersion = LibraryVersions.UI
-    mavenGroup = LibraryGroups.UI
+    mavenGroup = LibraryGroups.Compose.FOUNDATION
     inceptionYear = "2018"
     description = "Compose components that build the foundations from which to build a complete design system. This is for example used by Material to build its set of components."
 }
diff --git a/ui/ui-foundation/integration-tests/foundation-demos/build.gradle b/ui/ui-foundation/integration-tests/foundation-demos/build.gradle
index eb3f511..a75e404 100644
--- a/ui/ui-foundation/integration-tests/foundation-demos/build.gradle
+++ b/ui/ui-foundation/integration-tests/foundation-demos/build.gradle
@@ -36,10 +36,10 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests:demos:common")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-animation")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-foundation:samples")
+    implementation project(":compose:foundation:foundation:samples")
     implementation project(":ui:ui-text-core")
 }
 
diff --git a/ui/ui-foundation/samples/build.gradle b/ui/ui-foundation/samples/build.gradle
index 87cf549..c1d796d 100644
--- a/ui/ui-foundation/samples/build.gradle
+++ b/ui/ui-foundation/samples/build.gradle
@@ -35,7 +35,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-animation")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text-core")
 }
diff --git a/ui/ui-graphics/samples/build.gradle b/ui/ui-graphics/samples/build.gradle
index c07d5ce..603ff91 100644
--- a/ui/ui-graphics/samples/build.gradle
+++ b/ui/ui-graphics/samples/build.gradle
@@ -36,7 +36,7 @@
     api project(":ui:ui-unit")
     implementation project(":ui:ui-util")
     implementation project(":ui:ui-graphics")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
 }
 
 android {
diff --git a/ui/ui-layout/build.gradle b/ui/ui-layout/build.gradle
index 964d22d..bfcaff7 100644
--- a/ui/ui-layout/build.gradle
+++ b/ui/ui-layout/build.gradle
@@ -46,7 +46,7 @@
     testImplementation(ANDROIDX_TEST_RUNNER)
     testImplementation(JUNIT)
 
-    androidTestImplementation project(":ui:ui-foundation")
+    androidTestImplementation project(":compose:foundation:foundation")
     androidTestImplementation project(":ui:ui-test")
 
     androidTestImplementation(ANDROIDX_TEST_RULES)
diff --git a/ui/ui-layout/integration-tests/layout-demos/build.gradle b/ui/ui-layout/integration-tests/layout-demos/build.gradle
index c046cdb..134711b 100644
--- a/ui/ui-layout/integration-tests/layout-demos/build.gradle
+++ b/ui/ui-layout/integration-tests/layout-demos/build.gradle
@@ -37,7 +37,7 @@
     implementation project(":ui:ui-layout:samples")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-text")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
 }
 
 android {
diff --git a/ui/ui-layout/samples/build.gradle b/ui/ui-layout/samples/build.gradle
index fd8a2c3..f4305f6 100644
--- a/ui/ui-layout/samples/build.gradle
+++ b/ui/ui-layout/samples/build.gradle
@@ -34,7 +34,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-text")
 }
diff --git a/ui/ui-livedata/samples/build.gradle b/ui/ui-livedata/samples/build.gradle
index 867fb39..fd22395 100644
--- a/ui/ui-livedata/samples/build.gradle
+++ b/ui/ui-livedata/samples/build.gradle
@@ -31,7 +31,7 @@
     implementation(KOTLIN_STDLIB)
     implementation project(":annotation:annotation-sampled")
     implementation project(":ui:ui-livedata")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
 }
 
 android {
diff --git a/ui/ui-material/build.gradle b/ui/ui-material/build.gradle
index 15e53ec..55dda85 100644
--- a/ui/ui-material/build.gradle
+++ b/ui/ui-material/build.gradle
@@ -38,8 +38,8 @@
     api project(":compose:compose-runtime")
     implementation project(":ui:ui-util")
     api project(":ui:ui-core")
-    api project(":ui:ui-foundation")
-    api project(":ui:ui-material-icons-core")
+    api project(":compose:foundation:foundation")
+    api project(":compose:material:material-icons-core")
     api project(":ui:ui-text-core")
     api project(":ui:ui-text")
     api project(":ui:ui-animation-core")
@@ -52,7 +52,7 @@
     testImplementation(JUNIT)
     testImplementation(TRUTH)
 
-    androidTestImplementation project(":ui:ui-material:samples")
+    androidTestImplementation project(":compose:material:material:samples")
     androidTestImplementation project(":ui:ui-test")
     androidTestImplementation project(":test-screenshot")
 
@@ -71,7 +71,7 @@
     name = "Androidx Material"
     publish = Publish.SNAPSHOT_AND_RELEASE
     mavenVersion = LibraryVersions.UI
-    mavenGroup = LibraryGroups.UI
+    mavenGroup = LibraryGroups.Compose.MATERIAL
     inceptionYear = "2018"
     description = "AndroidX Material"
 }
diff --git a/ui/ui-material/icons/README.md b/ui/ui-material/icons/README.md
index 69b347a..98205c1 100644
--- a/ui/ui-material/icons/README.md
+++ b/ui/ui-material/icons/README.md
@@ -4,8 +4,8 @@
 Material iconography is split across three modules:
 
  1. The `generator` module, in `generator/` - this module processes and generates Kotlin source files as part of the build step of the other modules. This module is not shipped as an artifact, and caches its outputs based on the input icons (found in `generator/raw-icons`).
- 2. `ui-material-icons-core` , in `core/` - this module contains _core_ icons, the set of most-commonly-used icons used by applications, including the icons that are required by Material components themselves, such as the menu icon. This module is fairly small and is depended on by `ui-material`.
- 3. `ui-material-icons-extended`, in `extended/` - this module contains every icon that is not in `ui-material-icons-core`, and has a transitive `api` dependency on `ui-material-icons-core`, so depending on this module will provide every single Material icon (over 5000 at the time of writing). Due to the excessive size of this module, this module should ***NOT*** be included as a direct dependency of any other library, and should only be used if Proguard / R8 is enabled.
+ 2. `material-icons-core` , in `core/` - this module contains _core_ icons, the set of most-commonly-used icons used by applications, including the icons that are required by Material components themselves, such as the menu icon. This module is fairly small and is depended on by `material`.
+ 3. `material-icons-extended`, in `extended/` - this module contains every icon that is not in `material-icons-core`, and has a transitive `api` dependency on `material-icons-core`, so depending on this module will provide every single Material icon (over 5000 at the time of writing). Due to the excessive size of this module, this module should ***NOT*** be included as a direct dependency of any other library, and should only be used if Proguard / R8 is enabled.
 
 ## Icon Generation
 
diff --git a/ui/ui-material/icons/core/build.gradle b/ui/ui-material/icons/core/build.gradle
index 5c8f1d1..9259547 100644
--- a/ui/ui-material/icons/core/build.gradle
+++ b/ui/ui-material/icons/core/build.gradle
@@ -40,7 +40,7 @@
     name = "AndroidX Core Material Icons"
     publish = Publish.SNAPSHOT_AND_RELEASE
     mavenVersion = LibraryVersions.UI
-    mavenGroup = LibraryGroups.UI
+    mavenGroup = LibraryGroups.Compose.MATERIAL
     inceptionYear = "2020"
     description = "AndroidX Core Material Icons"
 }
diff --git a/ui/ui-material/icons/core/samples/build.gradle b/ui/ui-material/icons/core/samples/build.gradle
index 7b32914..35b7723 100644
--- a/ui/ui-material/icons/core/samples/build.gradle
+++ b/ui/ui-material/icons/core/samples/build.gradle
@@ -33,8 +33,8 @@
     implementation project(":annotation:annotation-sampled")
 
     implementation project(":compose:compose-runtime")
-    implementation project(":ui:ui-material")
-    implementation project(":ui:ui-material-icons-core")
+    implementation project(":compose:material:material")
+    implementation project(":compose:material:material-icons-core")
 }
 
 android {
diff --git a/ui/ui-material/icons/extended/build.gradle b/ui/ui-material/icons/extended/build.gradle
index 174ce2a..7a434d9 100644
--- a/ui/ui-material/icons/extended/build.gradle
+++ b/ui/ui-material/icons/extended/build.gradle
@@ -33,10 +33,10 @@
     kotlinPlugin project(path: ":compose:compose-compiler")
     implementation(KOTLIN_STDLIB)
 
-    api project(":ui:ui-material-icons-core")
+    api project(":compose:material:material-icons-core")
     implementation project(":compose:compose-runtime")
 
-    androidTestImplementation project(":ui:ui-foundation")
+    androidTestImplementation project(":compose:foundation:foundation")
     androidTestImplementation project(":ui:ui-layout")
     androidTestImplementation project(":ui:ui-core")
     androidTestImplementation project(":ui:ui-test")
@@ -59,7 +59,7 @@
     name = "AndroidX Extended Material Icons"
     publish = Publish.SNAPSHOT_AND_RELEASE
     mavenVersion = LibraryVersions.UI
-    mavenGroup = LibraryGroups.UI
+    mavenGroup = LibraryGroups.Compose.MATERIAL
     // This module has a large number (5000+) of generated source files and so doc generation /
     // API tracking will simply take too long
     toolingProject = true
diff --git a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/CoreIcons.kt b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/CoreIcons.kt
index 1c61a3d..3c15eb5 100644
--- a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/CoreIcons.kt
+++ b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/CoreIcons.kt
@@ -18,7 +18,7 @@
 
 /**
  * List of 'core' icons that will be added to the 'core' icons module, and depended on by
- * ui-material. These icons are the set of most commonly used icons, including icons used by
+ * material. These icons are the set of most commonly used icons, including icons used by
  * Material components directly (such as the menu icon in an AppBar). All icons not specified
  * here will be generated to the 'extended' icons module.
  */
diff --git a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/tasks/IconGenerationTask.kt b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/tasks/IconGenerationTask.kt
index 79f05ae..6fe7284 100644
--- a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/tasks/IconGenerationTask.kt
+++ b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/tasks/IconGenerationTask.kt
@@ -117,7 +117,7 @@
 }
 
 // Path to the generator project
-private const val GeneratorProject = ":ui:ui-material:icons:generator"
+private const val GeneratorProject = ":compose:material:material:icons:generator"
 
 /**
  * Registers a new [T] in [this], and sets [IconGenerationTask.buildDirectory] depending on
diff --git a/ui/ui-material/integration-tests/material-demos/build.gradle b/ui/ui-material/integration-tests/material-demos/build.gradle
index 472abad..3888f93 100644
--- a/ui/ui-material/integration-tests/material-demos/build.gradle
+++ b/ui/ui-material/integration-tests/material-demos/build.gradle
@@ -19,12 +19,12 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests:demos:common")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material:samples")
+    implementation project(":compose:material:material:samples")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-android-view")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
 }
 
 android {
diff --git a/ui/ui-material/integration-tests/material-studies/build.gradle b/ui/ui-material/integration-tests/material-studies/build.gradle
index 0d8f3e5..83e5b89 100644
--- a/ui/ui-material/integration-tests/material-studies/build.gradle
+++ b/ui/ui-material/integration-tests/material-studies/build.gradle
@@ -37,11 +37,11 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests:demos:common")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-animation")
     implementation project(":ui:ui-text-core")
-    implementation project(':ui:ui-material')
+    implementation project(':compose:material:material')
 }
 
 android {
diff --git a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/Icons.kt b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/Icons.kt
index b9c2597..16a8967 100644
--- a/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/Icons.kt
+++ b/ui/ui-material/integration-tests/material-studies/src/main/java/androidx/ui/material/studies/rally/Icons.kt
@@ -53,11 +53,11 @@
 }
 
 /**
- * Icons below are copied from [Icons.Filled] in ui-material-icons-extended to avoid recompiling the
+ * Icons below are copied from [Icons.Filled] in material-icons-extended to avoid recompiling the
  * module in demos. In the future when we release a stable artifact we could directly depend on
  * that, instead of a project dependency which causes recompilation.
  *
- * If the generated icons change, just build ui-material-icons-extended and copy the generated
+ * If the generated icons change, just build material-icons-extended and copy the generated
  * file, which should appear in Studio sources by searching for the name of that icon.
  */
 
diff --git a/ui/ui-material/samples/build.gradle b/ui/ui-material/samples/build.gradle
index 6b225e2..eda89ec 100644
--- a/ui/ui-material/samples/build.gradle
+++ b/ui/ui-material/samples/build.gradle
@@ -35,9 +35,9 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-animation")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
-    implementation project(":ui:ui-material")
+    implementation project(":compose:material:material")
     implementation project(":ui:ui-text-core")
 }
 
diff --git a/ui/ui-rxjava2/samples/build.gradle b/ui/ui-rxjava2/samples/build.gradle
index 1bb8884..1c2c94ea 100644
--- a/ui/ui-rxjava2/samples/build.gradle
+++ b/ui/ui-rxjava2/samples/build.gradle
@@ -31,7 +31,7 @@
     implementation(KOTLIN_STDLIB)
     implementation project(":annotation:annotation-sampled")
     implementation project(":ui:ui-rxjava2")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
 }
 
 android {
diff --git a/ui/ui-test/build.gradle b/ui/ui-test/build.gradle
index f809e12..5c0d5a0 100644
--- a/ui/ui-test/build.gradle
+++ b/ui/ui-test/build.gradle
@@ -44,7 +44,7 @@
 
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-animation")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-util")
     implementation project(":ui:ui-text")
@@ -54,7 +54,7 @@
 
     androidTestImplementation(TRUTH)
     androidTestImplementation project(":ui:ui-core")
-    androidTestImplementation project(':ui:ui-material')
+    androidTestImplementation project(':compose:material:material')
 }
 
 android {
diff --git a/ui/ui-text-core/integration-tests/text-demos/build.gradle b/ui/ui-text-core/integration-tests/text-demos/build.gradle
index 6ac8babb..5ed7d8b 100644
--- a/ui/ui-text-core/integration-tests/text-demos/build.gradle
+++ b/ui/ui-text-core/integration-tests/text-demos/build.gradle
@@ -17,7 +17,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests:demos:common")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-text-core:samples")
diff --git a/ui/ui-text-core/samples/build.gradle b/ui/ui-text-core/samples/build.gradle
index 26f61ec..169d544 100644
--- a/ui/ui-text-core/samples/build.gradle
+++ b/ui/ui-text-core/samples/build.gradle
@@ -34,7 +34,7 @@
 
     implementation project(":compose:compose-runtime")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-text-core")
 }
 
diff --git a/ui/ui-text/integration-tests/ui-text-compose-demos/build.gradle b/ui/ui-text/integration-tests/ui-text-compose-demos/build.gradle
index 6ac8babb..5ed7d8b 100644
--- a/ui/ui-text/integration-tests/ui-text-compose-demos/build.gradle
+++ b/ui/ui-text/integration-tests/ui-text-compose-demos/build.gradle
@@ -17,7 +17,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests:demos:common")
     implementation project(":ui:ui-core")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-layout")
     implementation project(":ui:ui-text-core")
     implementation project(":ui:ui-text-core:samples")
diff --git a/ui/ui-text/samples/build.gradle b/ui/ui-text/samples/build.gradle
index 46f66b6..47adc2c 100644
--- a/ui/ui-text/samples/build.gradle
+++ b/ui/ui-text/samples/build.gradle
@@ -33,7 +33,7 @@
     implementation project(":annotation:annotation-sampled")
 
     implementation project(":compose:compose-runtime")
-    implementation project(":ui:ui-foundation")
+    implementation project(":compose:foundation:foundation")
     implementation project(":ui:ui-text")
     implementation project(":ui:ui-core")
 }
diff --git a/ui/ui-tooling/build.gradle b/ui/ui-tooling/build.gradle
index 3de1f67..70ced87 100644
--- a/ui/ui-tooling/build.gradle
+++ b/ui/ui-tooling/build.gradle
@@ -37,7 +37,7 @@
 
     api(project(":compose:compose-runtime"))
     api(project(":ui:ui-core"))
-    implementation(project(":ui:ui-material"))
+    implementation(project(":compose:material:material"))
     // kotlin-reflect is provided by Studio at runtime
     compileOnly(KOTLIN_REFLECT)
 
@@ -47,7 +47,7 @@
     androidTestImplementation(ANDROIDX_TEST_RUNNER)
     androidTestImplementation(ANDROIDX_TEST_RULES)
     androidTestImplementation project(":ui:ui-layout")
-    androidTestImplementation project(":ui:ui-foundation")
+    androidTestImplementation project(":compose:foundation:foundation")
     androidTestImplementation(TRUTH)
     androidTestImplementation(KOTLIN_REFLECT)
 }