[go: nahoru, domu]

Merge "Fix WithConstraints test failing on API 30" into androidx-master-dev
diff --git a/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java b/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
index bd51eb5..aac6d87 100644
--- a/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
+++ b/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
@@ -71,7 +71,7 @@
         /**
          * Restrict usage to code within packages whose groups share
          * the same library group prefix up to the last ".", so for
-         * example libraries foo.bar:lib1 amd foo.baz:lib2 share
+         * example libraries foo.bar:lib1 and foo.baz:lib2 share
          * the prefix "foo." and so they can use each other's
          * apis that are restricted to this scope. Similarly for
          * com.foo.bar:lib1 and com.foo.baz:lib2 where they share
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
index bdc7ed8..8ffece6 100644
--- a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
@@ -18,6 +18,7 @@
 
 import androidx.appcompat.res.ColorStateListAlphaDetector
 import androidx.appcompat.res.ColorStateListLoadingDetector
+import androidx.appcompat.res.DrawableLoadingDetector
 import androidx.appcompat.res.ImageViewTintDetector
 import com.android.tools.lint.client.api.IssueRegistry
 import com.android.tools.lint.detector.api.CURRENT_API
@@ -27,6 +28,7 @@
     override val issues get() = listOf(
         ColorStateListAlphaDetector.NOT_USING_ANDROID_ALPHA,
         ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING,
+        DrawableLoadingDetector.NOT_USING_COMPAT_LOADING,
         ImageViewTintDetector.USING_ANDROID_TINT
     )
 }
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt
new file mode 100644
index 0000000..9d7123f
--- /dev/null
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt
@@ -0,0 +1,151 @@
+/*
+ * 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.appcompat.res
+
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+
+// Base class for all AppCompat Lint checks that flag usages of methods that should be
+// converted to use matching API(s) provided by AppCompat.
+@Suppress("UnstableApiUsage")
+abstract class BaseMethodDeprecationDetector(
+    private val issue: Issue,
+    vararg val conditions: DeprecationCondition
+) : Detector(), SourceCodeScanner {
+
+    // Collect unique method names from all deprecation conditions defined in this detector
+    private val applicableMethods = conditions.map { it.methodLocation.methodName }.distinct()
+
+    interface Predicate {
+        fun matches(context: JavaContext, node: UCallExpression, method: PsiMethod): Boolean
+    }
+
+    class ApiAtOrAbove(private val sdkLevel: Int) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            return context.mainProject.minSdkVersion.featureLevel >= sdkLevel
+        }
+    }
+
+    class ApiAbove(private val sdkLevel: Int) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            return context.mainProject.minSdkVersion.featureLevel > sdkLevel
+        }
+    }
+
+    class ApiAtOrBelow(private val sdkLevel: Int) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            return context.mainProject.minSdkVersion.featureLevel <= sdkLevel
+        }
+    }
+
+    class ApiBelow(private val sdkLevel: Int) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            return context.mainProject.minSdkVersion.featureLevel < sdkLevel
+        }
+    }
+
+    class MethodLocation(
+        private val className: String,
+        val methodName: String,
+        private vararg val params: String
+    ) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            if (!context.evaluator.isMemberInClass(method, className)) {
+                // Method is not in the right class
+                return false
+            }
+            if (method.name != methodName) {
+                // Method name does not match
+                return false
+            }
+            if (!context.evaluator.methodMatches(method, className, true, *params)) {
+                // Method signature does not match
+                return false
+            }
+            return true
+        }
+    }
+
+    class DeprecationCondition(
+        val methodLocation: MethodLocation,
+        val message: String,
+        private vararg val predicates: Predicate
+    ) : Predicate {
+        override fun matches(
+            context: JavaContext,
+            node: UCallExpression,
+            method: PsiMethod
+        ): Boolean {
+            if (!methodLocation.matches(context, node, method)) {
+                // Method location does not match. The whole condition is not applicable
+                return false
+            }
+
+            for (predicate in predicates) {
+                if (!predicate.matches(context, node, method)) {
+                    // The predicate does not match. The whole condition is not applicable
+                    return false
+                }
+            }
+            return true
+        }
+    }
+
+    // Mark final so that extending classes are forced to only use the constructor-level
+    // configuration APIs
+    final override fun getApplicableMethodNames(): List<String>? = applicableMethods
+
+    // Mark final so that extending classes are forced to only use the constructor-level
+    // configuration APIs
+    final override fun visitMethodCall(
+        context: JavaContext,
+        node: UCallExpression,
+        method: PsiMethod
+    ) {
+        // Find the first condition that matches and report the issue
+        for (condition in conditions) {
+            if (condition.matches(context, node, method)) {
+                context.report(issue, context.getLocation(node), condition.message)
+                return
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
index 55d4f82..0477130 100644
--- a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
@@ -16,22 +16,35 @@
 
 package androidx.appcompat.res
 
+import com.android.tools.lint.client.api.TYPE_INT
 import com.android.tools.lint.detector.api.Category
-import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
 import com.android.tools.lint.detector.api.Issue
-import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
 import com.android.tools.lint.detector.api.Severity
-import com.android.tools.lint.detector.api.SourceCodeScanner
-import com.intellij.psi.PsiMethod
-import org.jetbrains.uast.UCallExpression
 
+// Flags usage of Resources.getColorStateList and suggests converting it to either
+// ContextCompat.getColorStateList or AppCompatResources.getColorStateList based
+// on the API level
 @Suppress("UnstableApiUsage")
-class ColorStateListLoadingDetector : Detector(), SourceCodeScanner {
+class ColorStateListLoadingDetector : BaseMethodDeprecationDetector(
+    NOT_USING_COMPAT_LOADING,
+    // Suggest using ContextCompat.getColorStateList at API > 23
+    DeprecationCondition(
+        MethodLocation("android.content.res.Resources", "getColorStateList", TYPE_INT),
+        "Use `ContextCompat.getColorStateList()`",
+        ApiAbove(23)
+    ),
+    // Suggest using AppCompatResources.getColorStateList at API <= 23
+    DeprecationCondition(
+        MethodLocation("android.content.res.Resources", "getColorStateList", TYPE_INT),
+        "Use `AppCompatResources.getColorStateList()`",
+        ApiAtOrBelow(23)
+    )
+) {
     companion object {
         internal val NOT_USING_COMPAT_LOADING: Issue = Issue.create(
-            "UseCompatLoading",
+            "UseCompatLoadingForColorStateLists",
             "Should not call `Resources.getColorStateList` directly",
             "Use Compat loading of color state lists",
             Category.CORRECTNESS,
@@ -40,22 +53,4 @@
             Implementation(ColorStateListLoadingDetector::class.java, Scope.JAVA_FILE_SCOPE)
         )
     }
-
-    override fun getApplicableMethodNames(): List<String>? = listOf("getColorStateList")
-
-    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
-        // Only flag Resources.getColorStateList calls with one argument (parameter)
-        if (context.evaluator.isMemberInClass(method, "android.content.res.Resources") &&
-            (node.valueArgumentCount == 1)
-        ) {
-            val message = if (context.mainProject.minSdkVersion.featureLevel > 23)
-                "Use `ContextCompat.getColorStateList()`" else
-                "Use `AppCompatResources.getColorStateList()`"
-            context.report(
-                NOT_USING_COMPAT_LOADING,
-                context.getLocation(node),
-                message
-            )
-        }
-    }
 }
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt
new file mode 100644
index 0000000..1dcc823
--- /dev/null
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.appcompat.res
+
+import com.android.tools.lint.client.api.TYPE_INT
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+
+// Flags usage of Context.getDrawable and Resources.getDrawable and suggests converting them
+// to either ContextCompat.getDrawable or ResourcesCompat.getDrawable
+@Suppress("UnstableApiUsage")
+class DrawableLoadingDetector : BaseMethodDeprecationDetector(
+    NOT_USING_COMPAT_LOADING,
+    // Suggest using ContextCompat.getDrawable
+    DeprecationCondition(
+        MethodLocation("android.content.Context", "getDrawable", TYPE_INT),
+        "Use `ContextCompat.getDrawable()`"
+    ),
+    // Suggest using ResourcesCompat.getDrawable for one-parameter Resources.getDrawable calls
+    DeprecationCondition(
+        MethodLocation("android.content.res.Resources", "getDrawable", TYPE_INT),
+        "Use `ResourcesCompat.getDrawable()`"
+    ),
+    // Suggest using ResourcesCompat.getDrawable for two-parameter Resources.getDrawable calls
+    DeprecationCondition(
+        MethodLocation("android.content.res.Resources", "getDrawable", TYPE_INT,
+            "android.content.res.Resources.Theme"),
+        "Use `ResourcesCompat.getDrawable()`"
+    )
+) {
+    companion object {
+        internal val NOT_USING_COMPAT_LOADING: Issue = Issue.create(
+            "UseCompatLoadingForDrawables",
+            "Should not call `Context.getDrawable` or `Resources.getDrawable` directly",
+            "Use Compat loading of drawables",
+            Category.CORRECTNESS,
+            1,
+            Severity.WARNING,
+            Implementation(DrawableLoadingDetector::class.java, Scope.JAVA_FILE_SCOPE)
+        )
+    }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
index b3f550a..8aadf18 100644
--- a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
+++ b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
@@ -110,7 +110,7 @@
         ).issues(ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING)
             .run()
             .expect("""
-src/com/example/CustomActivity.kt:8: Warning: Use ContextCompat.getColorStateList() [UseCompatLoading]
+src/com/example/CustomActivity.kt:8: Warning: Use ContextCompat.getColorStateList() [UseCompatLoadingForColorStateLists]
         getResources().getColorStateList(R.color.color_state_list)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 0 errors, 1 warnings
@@ -167,7 +167,7 @@
         ).issues(ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING)
             .run()
             .expect("""
-src/com/example/CustomActivity.kt:8: Warning: Use AppCompatResources.getColorStateList() [UseCompatLoading]
+src/com/example/CustomActivity.kt:8: Warning: Use AppCompatResources.getColorStateList() [UseCompatLoadingForColorStateLists]
         getResources().getColorStateList(R.color.color_state_list)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 0 errors, 1 warnings
diff --git a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt
new file mode 100644
index 0000000..de28066
--- /dev/null
+++ b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt
@@ -0,0 +1,165 @@
+/*
+ * 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.appcompat.lint.res
+
+import androidx.appcompat.lint.Stubs
+import androidx.appcompat.res.DrawableLoadingDetector
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
+import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
+import org.junit.Test
+
+class DrawableLoadingDetectorTest {
+    @Test
+    fun testCustomGetDrawable() {
+        val customActivity = kotlin(
+            "com/example/CustomActivity.kt",
+            """
+            package com.example
+
+            import android.graphics.drawable.Drawable
+            import androidx.appcompat.app.AppCompatActivity
+            import androidx.core.content.ContextCompat
+
+            class ResourceLoader {
+                private fun getDrawable(resourceId: Int): Drawable {
+                    return ContextCompat.getDrawable(CustomActivity.this, resourceId)
+                }
+            }
+
+            class CustomActivity: AppCompatActivity() {
+                override fun onCreate(savedInstanceState: Bundle?) {
+                   ResourceLoader().getDrawable(android.R.drawable.ic_delete)
+                }
+            }
+            """
+        ).indented().within("src")
+
+        // We expect a clean Lint run since the call to getDrawable in activity's onCreate
+        // is on our own custom inner class
+        lint().files(
+            Stubs.APPCOMPAT_ACTIVITY,
+            customActivity
+        ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun testCoreContextGetDrawable() {
+        val customActivity = kotlin(
+            "com/example/CustomActivity.kt",
+            """
+            package com.example
+
+            import android.graphics.drawable.Drawable
+            import android.os.Bundle
+            import androidx.appcompat.app.AppCompatActivity
+
+            class CustomActivity: AppCompatActivity() {
+                override fun onCreate(savedInstanceState: Bundle?) {
+                    getDrawable(android.R.drawable.ic_delete)
+                }
+            }
+            """
+        ).indented().within("src")
+
+        // We expect the call to Context.getDrawable to be flagged to use ContextCompat loading
+        /* ktlint-disable max-line-length */
+        lint().files(
+            Stubs.APPCOMPAT_ACTIVITY,
+            customActivity
+        ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+            .run()
+            .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ContextCompat.getDrawable() [UseCompatLoadingForDrawables]
+        getDrawable(android.R.drawable.ic_delete)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+            """.trimIndent())
+        /* ktlint-enable max-line-length */
+    }
+
+    @Test
+    fun testCoreResourcesGetDrawable() {
+        val customActivity = kotlin(
+            "com/example/CustomActivity.kt",
+            """
+            package com.example
+
+            import android.graphics.drawable.Drawable
+            import android.os.Bundle
+            import androidx.appcompat.app.AppCompatActivity
+
+            class CustomActivity: AppCompatActivity() {
+                override fun onCreate(savedInstanceState: Bundle?) {
+                    getResources().getDrawable(android.R.drawable.ic_delete)
+                }
+            }
+            """
+        ).indented().within("src")
+
+        // We expect the call to Resources.getDrawable to be flagged to use ResourcesCompat loading
+        /* ktlint-disable max-line-length */
+        lint().files(
+            Stubs.APPCOMPAT_ACTIVITY,
+            customActivity
+        ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+            .run()
+            .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ResourcesCompat.getDrawable() [UseCompatLoadingForDrawables]
+        getResources().getDrawable(android.R.drawable.ic_delete)
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+            """.trimIndent())
+        /* ktlint-enable max-line-length */
+    }
+
+    @Test
+    fun testCoreResourcesThemeGetDrawable() {
+        val customActivity = kotlin(
+            "com/example/CustomActivity.kt",
+            """
+            package com.example
+
+            import android.graphics.drawable.Drawable
+            import android.os.Bundle
+            import androidx.appcompat.app.AppCompatActivity
+
+            class CustomActivity: AppCompatActivity() {
+                override fun onCreate(savedInstanceState: Bundle?) {
+                    getResources().getDrawable(android.R.drawable.ic_delete, getTheme())
+                }
+            }
+            """
+        ).indented().within("src")
+
+        // We expect the call to Resources.getDrawable to be flagged to use ResourcesCompat loading
+        /* ktlint-disable max-line-length */
+        lint().files(
+            Stubs.APPCOMPAT_ACTIVITY,
+            customActivity
+        ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+            .run()
+            .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ResourcesCompat.getDrawable() [UseCompatLoadingForDrawables]
+        getResources().getDrawable(android.R.drawable.ic_delete, getTheme())
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+            """.trimIndent())
+        /* ktlint-enable max-line-length */
+    }
+}
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt
new file mode 100644
index 0000000..71b8c84
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.appcompat.app
+
+import android.view.InflateException
+import android.widget.Toast
+import androidx.appcompat.testutils.NightModeActivityTestRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import junit.framework.TestCase.assertNotNull
+import junit.framework.TestCase.assertNull
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class NightModeBaseContextThemeTestCase {
+    @get:Rule
+    val rule = NightModeActivityTestRule(NightModeActivity::class.java)
+
+    @Test
+    fun testBaseContextShowToast() {
+        var result: Exception? = null
+
+        rule.runOnUiThread {
+            try {
+                Toast.makeText(rule.activity.baseContext, "test", Toast.LENGTH_SHORT).show()
+            } catch (e: InflateException) {
+                e.printStackTrace()
+                result = e
+            }
+        }
+
+        assertNull("Showed Toast without exception", result)
+    }
+
+    @Test
+    fun testBaseContextResolveAttribute() {
+        var baseContext = rule.activity.baseContext
+        var resolved = baseContext.obtainStyledAttributes(
+            intArrayOf(android.R.attr.textColorLink))
+        assertNotNull("Resolved @attr/textColorLink", resolved.getColorStateList(0))
+    }
+}
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
index cd5c5c79..0ce4cb2 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -446,7 +446,7 @@
         // Next, we'll wrap the base context to ensure any method overrides or themes are left
         // intact. Since ThemeOverlay.AppCompat theme is empty, we'll get the base context's theme.
         final ContextThemeWrapper wrappedContext = new ContextThemeWrapper(baseContext,
-                R.style.ThemeOverlay_AppCompat);
+                R.style.Theme_AppCompat_Empty);
         wrappedContext.applyOverrideConfiguration(config);
 
         // Check whether the base context has an explicit theme or is able to obtain one
diff --git a/appcompat/appcompat/src/main/res/values/themes.xml b/appcompat/appcompat/src/main/res/values/themes.xml
index 28ea38e..f2c0ed6 100644
--- a/appcompat/appcompat/src/main/res/values/themes.xml
+++ b/appcompat/appcompat/src/main/res/values/themes.xml
@@ -25,6 +25,9 @@
          that need to vary based on platform version should be defined in the corresponding
          "Theme.Base" theme. -->
 
+    <!-- Empty theme used to create a no-op ContextThemeWrapper. -->
+    <style name="Theme.AppCompat.Empty" parent="" />
+
     <!-- Platform-independent theme providing an action bar in a dark-themed activity. -->
     <style name="Theme.AppCompat" parent="Base.Theme.AppCompat" />
 
diff --git a/benchmark/common/api/1.1.0-alpha01.ignore b/benchmark/common/api/1.1.0-alpha01.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha01.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+    Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/1.1.0-alpha01.txt b/benchmark/common/api/1.1.0-alpha01.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/1.1.0-alpha01.txt
+++ b/benchmark/common/api/1.1.0-alpha01.txt
@@ -14,8 +14,5 @@
   public static final class BenchmarkState.Companion {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/api/current.txt b/benchmark/common/api/current.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/current.txt
+++ b/benchmark/common/api/current.txt
@@ -14,8 +14,5 @@
   public static final class BenchmarkState.Companion {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
index e87771e..907fabb 100644
--- a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -21,8 +21,5 @@
   @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/api/public_plus_experimental_current.txt b/benchmark/common/api/public_plus_experimental_current.txt
index e87771e..907fabb 100644
--- a/benchmark/common/api/public_plus_experimental_current.txt
+++ b/benchmark/common/api/public_plus_experimental_current.txt
@@ -21,8 +21,5 @@
   @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.ignore b/benchmark/common/api/restricted_1.1.0-alpha01.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+    Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.txt b/benchmark/common/api/restricted_1.1.0-alpha01.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/restricted_1.1.0-alpha01.txt
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.txt
@@ -14,8 +14,5 @@
   public static final class BenchmarkState.Companion {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/api/restricted_current.txt b/benchmark/common/api/restricted_current.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/restricted_current.txt
+++ b/benchmark/common/api/restricted_current.txt
@@ -14,8 +14,5 @@
   public static final class BenchmarkState.Companion {
   }
 
-  public final class TraceCompatKt {
-  }
-
 }
 
diff --git a/benchmark/common/build.gradle b/benchmark/common/build.gradle
index edbc120..047827b 100644
--- a/benchmark/common/build.gradle
+++ b/benchmark/common/build.gradle
@@ -31,6 +31,7 @@
     implementation(KOTLIN_STDLIB)
     api("androidx.annotation:annotation:1.0.0")
     api("androidx.annotation:annotation-experimental:1.0.0-rc01")
+    implementation(project(':tracing:tracing-ktx'))
     implementation(ANDROIDX_TEST_MONITOR)
 
     androidTestImplementation(ANDROIDX_TEST_RULES)
diff --git a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
index 10c0751..4cee094 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
@@ -27,6 +27,7 @@
 import androidx.annotation.VisibleForTesting
 import androidx.benchmark.Errors.PREFIX
 import androidx.test.platform.app.InstrumentationRegistry
+import androidx.tracing.Trace
 import java.io.File
 import java.text.NumberFormat
 import java.util.concurrent.TimeUnit
@@ -176,7 +177,7 @@
     }
 
     private fun beginWarmup() {
-        beginTraceSection("Warmup")
+        Trace.beginSection("Warmup")
         // Run GC to avoid memory pressure from previous run from affecting this one.
         // Note, we don't use System.gc() because it doesn't always have consistent behavior
         Runtime.getRuntime().gc()
@@ -217,12 +218,12 @@
         thermalThrottleSleepSeconds = 0
         state = RUNNING
         metrics.captureInit()
-        beginTraceSection("Benchmark")
+        Trace.beginSection("Benchmark")
         metrics.captureStart()
     }
 
     private fun endBenchmark() {
-        endTraceSection() // paired with start in beginBenchmark()
+        Trace.endSection() // paired with start in beginBenchmark()
         when (Arguments.profilingMode) {
             ProfilingMode.Sampled, ProfilingMode.Method -> {
                 Debug.stopMethodTracing()
@@ -364,7 +365,7 @@
 
                 throwIfPaused() // check each loop during warmup
                 if (warmupManager.onNextIteration(lastDuration)) {
-                    endTraceSection() // paired with start in beginWarmup()
+                    Trace.endSection() // paired with start in beginWarmup()
                     beginBenchmark()
                 }
                 return true
diff --git a/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt b/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt
deleted file mode 100644
index 491fe42..0000000
--- a/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2019 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.benchmark
-
-import android.os.Build
-import android.os.Trace
-import androidx.annotation.RestrictTo
-
-/*
- * Simple reimplementation of TraceCompat, to avoid androidx.core dependency for two methods
- *
- * Note:
- * Benchmark isn't especially careful about terminating tracing sections, because our APIs are
- * called *from* the long-running synchronous chunks of work, instead of wrapping them.
- *
- * We try and match up begi/end pairs, but it's entirely possibly that ends will be missed due to
- * the app returning early from the benchmark loop (whether intentionally, or by crashing).
- *
- * Because there's no elegant way to fix this, we just accept that crashing benchmarks can result in
- * never-terminating traces from benchmark.
- */
-
-/**
- * @suppress
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun beginTraceSection(sectionName: String) {
-    if (Build.VERSION.SDK_INT >= 18) {
-        Trace.beginSection(sectionName)
-    }
-}
-
-/**
- * @suppress
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun endTraceSection() {
-    if (Build.VERSION.SDK_INT >= 18) {
-        Trace.endSection()
-    }
-}
\ No newline at end of file
diff --git a/benchmark/junit4/build.gradle b/benchmark/junit4/build.gradle
index 8aef6fb..639c57a 100644
--- a/benchmark/junit4/build.gradle
+++ b/benchmark/junit4/build.gradle
@@ -33,6 +33,7 @@
 
 dependencies {
     api(project(":benchmark:benchmark-common"))
+    implementation(project(':tracing:tracing-ktx'))
 
     api(JUNIT)
     api(KOTLIN_STDLIB)
diff --git a/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt b/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
index 9d149e9..21aa740 100644
--- a/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
+++ b/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
@@ -20,9 +20,8 @@
 import android.util.Log
 import androidx.annotation.RestrictTo
 import androidx.benchmark.BenchmarkState
-import androidx.benchmark.beginTraceSection
-import androidx.benchmark.endTraceSection
 import androidx.test.rule.GrantPermissionRule
+import androidx.tracing.trace
 import org.junit.Assert.assertTrue
 import org.junit.rules.RuleChain
 import org.junit.rules.TestRule
@@ -188,11 +187,8 @@
             internalState.traceUniqueName = description.testClass.simpleName + "_" +
                     invokeMethodName
 
-            try {
-                beginTraceSection(description.displayName)
+            trace(description.displayName) {
                 base.evaluate()
-            } finally {
-                endTraceSection()
             }
 
             if (enableReport) {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
index 61d1cf7..cb58c7a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
@@ -36,6 +36,8 @@
 import android.opengl.EGLSurface;
 import android.opengl.GLES20;
 
+import java.util.Objects;
+
 /**
  * Utility functions interacting with OpenGL.
  *
@@ -46,11 +48,9 @@
     }
 
     /** Set up a GL context so that GL calls requiring a context can be made. */
-    // TODO(b/141957748): Suppressed during upgrade to AGP 3.6.
-    @SuppressWarnings("ReferenceEquality")
     private static void setupGLContext() {
         EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (eglDisplay == EGL_NO_DISPLAY) {
+        if (Objects.equals(eglDisplay, EGL_NO_DISPLAY)) {
             throw new RuntimeException("Unable to get EGL display.");
         }
         int[] majorVer = new int[1];
@@ -96,7 +96,7 @@
         EGLSurface eglPbuffer =
                 EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs,
                         pbufferAttribsOffset);
-        if (eglPbuffer == EGL_NO_SURFACE) {
+        if (Objects.equals(eglPbuffer, EGL_NO_SURFACE)) {
             throw new RuntimeException("Unable to create pbuffer surface.");
         }
 
@@ -106,7 +106,7 @@
                 EGL14.eglCreateContext(
                         eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs,
                         contextAttribsOffset);
-        if (eglContext == EGL_NO_CONTEXT) {
+        if (Objects.equals(eglContext, EGL_NO_CONTEXT)) {
             throw new RuntimeException("Unable to create EGL context.");
         }
 
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
index f609c48..3f47890 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
@@ -144,16 +144,15 @@
             if (mReleaseFuture == null) {
                 mReleaseFuture = CallbackToFutureAdapter.getFuture(
                         new CallbackToFutureAdapter.Resolver<Void>() {
-                            // TODO(b/141957748): Suppressed during upgrade to AGP 3.6.
-                            @SuppressWarnings("GuardedBy")
                             @Override
                             public Object attachCompleter(@NonNull
                                     CallbackToFutureAdapter.Completer<Void> completer) {
-                                Preconditions.checkState(Thread.holdsLock(mReleaseLock));
-                                Preconditions.checkState(mReleaseCompleter == null,
-                                        "Release completer expected to be null");
-                                mReleaseCompleter = completer;
-                                return "Release[imageProxy=" + FakeImageProxy.this + "]";
+                                synchronized (mReleaseLock) {
+                                    Preconditions.checkState(mReleaseCompleter == null,
+                                            "Release completer expected to be null");
+                                    mReleaseCompleter = completer;
+                                    return "Release[imageProxy=" + FakeImageProxy.this + "]";
+                                }
                             }
                         });
             }
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java b/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java
deleted file mode 100644
index 4f494cd..0000000
--- a/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2019 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.camera.view;
-
-import android.graphics.SurfaceTexture;
-import android.os.Build.VERSION_CODES;
-import android.util.Size;
-
-import androidx.annotation.RequiresApi;
-
-/**
- * An implementation of {@link SurfaceTexture} with a fixed default buffer size.
- *
- * <p>The fixed default buffer size used at construction time cannot be changed through the {@link
- * #setDefaultBufferSize(int, int)} method. This should only be used for the
- * {@link TextureViewImplementation} as a temporary solution to prevent the
- * {@link android.view.TextureView} from changing the resolution of the {@link SurfaceTexture},
- * because the {@link android.hardware.camera2.CameraCaptureSession} can not handle any arbitrary
- * resolution.
- */
-final class FixedSizeSurfaceTexture extends SurfaceTexture {
-    /**
-     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
-     *
-     * @param texName   the OpenGL texture object name (e.g. generated via glGenTextures)
-     * @param fixedSize the fixed default buffer size
-     * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
-     */
-    FixedSizeSurfaceTexture(int texName, Size fixedSize) {
-        super(texName);
-        super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
-    }
-
-    /**
-     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
-     *
-     * <p>In single buffered mode the application is responsible for serializing access to the image
-     * content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
-     * method must be called before the image content producer takes ownership of the buffer. For
-     * example, when producing image content with the NDK ANativeWindow_lock and
-     * ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
-     * ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
-     * {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
-     * frame.
-     *
-     * @param texName          the OpenGL texture object name (e.g. generated via glGenTextures)
-     * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
-     * @param fixedSize        the fixed default buffer size
-     * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
-     */
-    FixedSizeSurfaceTexture(int texName, boolean singleBufferMode, Size fixedSize) {
-        super(texName, singleBufferMode);
-        super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
-    }
-
-    /**
-     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
-     *
-     * <p>In single buffered mode the application is responsible for serializing access to the image
-     * content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
-     * method must be called before the image content producer takes ownership of the buffer. For
-     * example, when producing image content with the NDK ANativeWindow_lock and
-     * ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
-     * ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
-     * {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
-     * frame.
-     *
-     * <p>Unlike {@link SurfaceTexture(int, boolean)}, which takes an OpenGL texture object name,
-     * this constructor creates the SurfaceTexture in detached mode. A texture name must be passed
-     * in using {@link #attachToGLContext} before calling {@link #releaseTexImage()} and producing
-     * image content using OpenGL ES.
-     *
-     * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
-     * @param fixedSize        the fixed default buffer size
-     * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
-     */
-    @RequiresApi(api = VERSION_CODES.O)
-    FixedSizeSurfaceTexture(boolean singleBufferMode, Size fixedSize) {
-        super(singleBufferMode);
-        super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
-    }
-
-    /**
-     * This method has no effect.
-     *
-     * <p>Unlike {@link SurfaceTexture}, this method does not affect the default buffer size. The
-     * default buffer size will remain what it was set to during construction.
-     *
-     * @param width  ignored width
-     * @param height ignored height
-     */
-    @Override
-    public void setDefaultBufferSize(int width, int height) {
-        // No-op
-    }
-}
-
diff --git a/development/release-notes/GitClient.py b/development/release-notes/GitClient.py
index 257eee1..cabef02 100644
--- a/development/release-notes/GitClient.py
+++ b/development/release-notes/GitClient.py
@@ -137,8 +137,9 @@
 		self.summary = ""
 		self.changeType = CommitType.BUG_FIX
 		self.releaseNote = ""
-		self.releaseNoteDelimiter = "Relnote:"
-		listedCommit = gitCommit.split('\n')
+		self.releaseNoteDelimiter = "relnote:"
+		self.formatGitCommitRelnoteTag()
+		listedCommit = self.gitCommit.split('\n')
 		for line in listedCommit:
 			if line.strip() == "": continue
 			if self.commitSHADelimiter in line:
@@ -152,10 +153,20 @@
 			if ("Bug:" in line) or ("b/" in line) or ("bug:" in line) or ("Fixes:" in line) or ("fixes b/" in line):
 				self.getBugsFromGitLine(line)
 			if self.releaseNoteDelimiter in line:
-				self.getReleaseNotesFromGitLine(line, gitCommit)
+				self.getReleaseNotesFromGitLine(line, self.gitCommit)
 			if self.projectDir.strip('/') in line:
 				self.getFileFromGitLine(line)
 
+	def formatGitCommitRelnoteTag(self):
+		""" This method accounts for the fact that the releaseNoteDelimiter is case insensitive
+			To do this, we just replace it with the tag we expect and can easily parse
+		"""
+		relnoteIndex = self.gitCommit.lower().find(self.releaseNoteDelimiter)
+		if relnoteIndex > -1:
+			self.gitCommit = self.gitCommit[:relnoteIndex] + \
+						self.releaseNoteDelimiter + \
+						self.gitCommit[relnoteIndex + len(self.releaseNoteDelimiter):]
+
 	def isExternalAuthorEmail(self, authorEmail):
 		return "@google.com" not in self.authorEmail
 
diff --git a/development/release-notes/testReleaseNotes.py b/development/release-notes/testReleaseNotes.py
index a877008..95cb52e 100755
--- a/development/release-notes/testReleaseNotes.py
+++ b/development/release-notes/testReleaseNotes.py
@@ -168,6 +168,98 @@
 		)
 		self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
 
+	def test_parseAPICommitWithDefaultDelimitersAndUncapitalizedRelnoteTag(self):
+		commitWithApiChangeString = """
+				_CommitStart
+				_CommitSHA:mySha
+				_Author:anemail@google.com
+				_Date:Tue Aug 6 15:05:55 2019 -0700
+				_Subject:Added a new API!
+				_Body:Also fixed some other bugs
+
+				Here is an explanation of my commit
+
+				"This is a quote about why it's great!"
+
+				Bug: 123456
+				Bug: b/1234567
+				Fixes: 123123
+				Test: ./gradlew buildOnServer
+
+				relnote: Added an awesome new API!
+
+				Change-Id: myChangeId
+
+				projectdir/a.java
+				projectdir/b.java
+				projectdir/androidTest/c.java
+				projectdir/api/some_api_file.txt
+				projectdir/api/current.txt
+			"""
+		commitWithApiChange = Commit(commitWithApiChangeString, "/projectdir/")
+		self.assertEqual("mySha", commitWithApiChange.sha)
+		self.assertEqual("anemail@google.com", commitWithApiChange.authorEmail)
+		self.assertEqual("myChangeId", commitWithApiChange.changeId)
+		self.assertEqual("Added a new API!", commitWithApiChange.summary)
+		self.assertEqual(CommitType.API_CHANGE, commitWithApiChange.changeType)
+		self.assertEqual([123456, 1234567, 123123], commitWithApiChange.bugs)
+		self.assertEqual([
+				"projectdir/a.java",
+				"projectdir/b.java",
+				"projectdir/androidTest/c.java",
+				"projectdir/api/some_api_file.txt",
+				"projectdir/api/current.txt"
+			],
+			commitWithApiChange.files
+		)
+		self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
+
+	def test_parseAPICommitWithDefaultDelimitersAndCapitalizedRelnoteTag(self):
+		commitWithApiChangeString = """
+				_CommitStart
+				_CommitSHA:mySha
+				_Author:anemail@google.com
+				_Date:Tue Aug 6 15:05:55 2019 -0700
+				_Subject:Added a new API!
+				_Body:Also fixed some other bugs
+
+				Here is an explanation of my commit
+
+				"This is a quote about why it's great!"
+
+				Bug: 123456
+				Bug: b/1234567
+				Fixes: 123123
+				Test: ./gradlew buildOnServer
+
+				RelNotE: Added an awesome new API!
+
+				Change-Id: myChangeId
+
+				projectdir/a.java
+				projectdir/b.java
+				projectdir/androidTest/c.java
+				projectdir/api/some_api_file.txt
+				projectdir/api/current.txt
+			"""
+		commitWithApiChange = Commit(commitWithApiChangeString, "/projectdir/")
+		self.assertEqual("mySha", commitWithApiChange.sha)
+		self.assertEqual("anemail@google.com", commitWithApiChange.authorEmail)
+		self.assertEqual("myChangeId", commitWithApiChange.changeId)
+		self.assertEqual("Added a new API!", commitWithApiChange.summary)
+		self.assertEqual(CommitType.API_CHANGE, commitWithApiChange.changeType)
+		self.assertEqual([123456, 1234567, 123123], commitWithApiChange.bugs)
+		self.assertEqual([
+				"projectdir/a.java",
+				"projectdir/b.java",
+				"projectdir/androidTest/c.java",
+				"projectdir/api/some_api_file.txt",
+				"projectdir/api/current.txt"
+			],
+			commitWithApiChange.files
+		)
+		self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
+
 	def test_parseBugFixCommitWithCustomDelimiters(self):
 		commitSHADelimiter = "_MyCommitSHA:"
 		authorEmailDelimiter = "_MyAuthor:"
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 87e57e9..04c6674 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -43,6 +43,9 @@
     api(project(":lifecycle:lifecycle-viewmodel"))
     api(project(":lifecycle:lifecycle-viewmodel-savedstate"))
 
+    androidTestImplementation("androidx.appcompat:appcompat:1.1.0", {
+        exclude group: 'androidx.fragment', module: 'fragment'
+    })
     androidTestImplementation(KOTLIN_STDLIB)
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_CORE)
diff --git a/fragment/fragment/src/androidTest/AndroidManifest.xml b/fragment/fragment/src/androidTest/AndroidManifest.xml
index b55fe6e..5bac34a 100644
--- a/fragment/fragment/src/androidTest/AndroidManifest.xml
+++ b/fragment/fragment/src/androidTest/AndroidManifest.xml
@@ -50,6 +50,8 @@
         <activity android:name="androidx.fragment.app.SimpleContainerActivity" />
         <activity android:name="androidx.fragment.app.DialogActivity"
                   android:theme="@style/DialogTheme"/>
+        <activity android:name="androidx.fragment.app.TestAppCompatActivity"
+                  android:theme="@style/Theme.AppCompat.Light" />
     </application>
 
 </manifest>
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt
new file mode 100644
index 0000000..7ef6461
--- /dev/null
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt
@@ -0,0 +1,141 @@
+/*
+ * 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.fragment.app
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDialog
+import androidx.fragment.test.R
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+// the Layout used to inflate the view
+sealed class InflatedViewLayout {
+    abstract fun getLayoutId(): Int
+    abstract fun getChildFragment(f: Fragment): Fragment?
+    override fun toString(): String = this.javaClass.simpleName
+}
+// When to inflate the view
+sealed class InflateViewLocation {
+    override fun toString(): String = this.javaClass.simpleName
+}
+
+object UseFragmentContainerView : InflatedViewLayout() {
+    override fun getLayoutId() = R.layout.inflated_fragment_container_view
+    override fun getChildFragment(f: Fragment) =
+        f.childFragmentManager.findFragmentByTag("fragment1")
+}
+
+object UseFragmentTag : InflatedViewLayout() {
+    override fun getLayoutId() = R.layout.nested_inflated_fragment_parent
+    override fun getChildFragment(f: Fragment) =
+        f.childFragmentManager.findFragmentById(R.id.child_fragment)
+}
+
+object OnCreateDialog : InflateViewLocation()
+object OnCreateView : InflateViewLocation()
+
+@LargeTest
+@RunWith(Parameterized::class)
+class DialogFragmentInflatedChildTest(
+    private val inflatedView: InflatedViewLayout,
+    private val inflateLocation: InflateViewLocation
+) {
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "inflatedView={0}, inflateLocation={1}")
+        fun data() = mutableListOf<Array<Any>>().apply {
+            arrayOf(
+                UseFragmentContainerView,
+                UseFragmentTag
+            ).forEach { inflatedViewLayout ->
+                add(arrayOf(inflatedViewLayout, OnCreateDialog))
+                add(arrayOf(inflatedViewLayout, OnCreateView))
+            }
+        }
+    }
+
+    @Test
+    fun testInflatedChildDialogFragment() {
+        with(ActivityScenario.launch(SimpleContainerActivity::class.java)) {
+            val dialogFragment = TestInflatedChildDialogFragment(
+                false, inflatedView.getLayoutId(), inflateLocation is OnCreateDialog)
+
+            withActivity {
+                supportFragmentManager.beginTransaction()
+                    .add(dialogFragment, null)
+                    .commitNow()
+            }
+
+            val child = inflatedView.getChildFragment(dialogFragment)
+            assertWithMessage("Inflated child fragment should not be null")
+                .that(child).isNotNull()
+        }
+    }
+
+    @Test
+    fun testInflatedChildAppCompatDialogFragment() {
+        with(ActivityScenario.launch(TestAppCompatActivity::class.java)) {
+            val dialogFragment = TestInflatedChildDialogFragment(
+                true, inflatedView.getLayoutId(), inflateLocation is OnCreateDialog)
+
+            withActivity {
+                supportFragmentManager.beginTransaction()
+                    .add(dialogFragment, null)
+                    .commitNow()
+            }
+
+            val child = inflatedView.getChildFragment(dialogFragment)
+            assertWithMessage("Inflated child fragment should not be null")
+                .that(child).isNotNull()
+        }
+    }
+}
+
+// This Activity has an AppCompatTheme
+class TestAppCompatActivity : AppCompatActivity(R.layout.simple_container)
+
+class TestInflatedChildDialogFragment(
+    val useAppCompat: Boolean,
+    val layoutId: Int,
+    val onCreateDialog: Boolean
+) : DialogFragment() {
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ) = if (!onCreateDialog) inflater.inflate(layoutId, container, false) else null
+
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        val dialog =
+            if (useAppCompat) AppCompatDialog(requireContext()) else Dialog(requireContext())
+        if (onCreateDialog) {
+            dialog.setContentView(layoutInflater.inflate(layoutId, null))
+        }
+        return dialog
+    }
+}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
index a8c1715..2761130 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
@@ -39,6 +39,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.StyleRes;
+import androidx.core.view.LayoutInflaterCompat;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -128,6 +129,7 @@
     private boolean mCancelable = true;
     private boolean mShowsDialog = true;
     private int mBackStackId = -1;
+    private boolean mCreatingDialog;
 
     @Nullable
     private Dialog mDialog;
@@ -427,19 +429,32 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * If this is called from within {@link #onCreateDialog(Bundle)}, the layout inflater from
+     * {@link Fragment#onGetLayoutInflater(Bundle)}, without the dialog theme, will be returned.
+     */
     @Override
     @NonNull
     public LayoutInflater onGetLayoutInflater(@Nullable Bundle savedInstanceState) {
-        if (!mShowsDialog) {
+        if (!mShowsDialog || mCreatingDialog) {
             return super.onGetLayoutInflater(savedInstanceState);
         }
 
-        mDialog = onCreateDialog(savedInstanceState);
+        try {
+            mCreatingDialog = true;
+            mDialog = onCreateDialog(savedInstanceState);
+            setupDialog(mDialog, mStyle);
+        } finally {
+            mCreatingDialog = false;
+        }
 
-        setupDialog(mDialog, mStyle);
-
-        return (LayoutInflater) mDialog.getContext().getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
+        LayoutInflater layoutInflater = LayoutInflater.from(mDialog.getContext());
+        LayoutInflaterCompat.setFactory2(layoutInflater,
+                    mChildFragmentManager.getLayoutInflaterFactory());
+        return layoutInflater;
     }
 
     /** @hide */
diff --git a/heifwriter/heifwriter/lint-baseline.xml b/heifwriter/heifwriter/lint-baseline.xml
index 9dfbdcc..1ff86da 100644
--- a/heifwriter/heifwriter/lint-baseline.xml
+++ b/heifwriter/heifwriter/lint-baseline.xml
@@ -2,6 +2,16 @@
 <issues format="5" by="lint 3.6.0-beta05" client="gradle" variant="debug" version="3.6.0-beta05">
 
     <issue
+        id="NewApi"
+        message="Call requires API level 29 (current min is 28): `android.media.MediaCodecInfo#isHardwareAccelerated`"
+        errorLine1="                if (info.isHardwareAccelerated()) {"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/heifwriter/HeifEncoder.java"
+            line="401"
+            column="26"/>
+    </issue>
+    <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
         errorLine1="    public static FloatBuffer createFloatBuffer(float[] coords) {"
diff --git a/jetifier/jetifier/core/src/main/resources/default.config b/jetifier/jetifier/core/src/main/resources/default.config
index 493210a..9b14a9d 100644
--- a/jetifier/jetifier/core/src/main/resources/default.config
+++ b/jetifier/jetifier/core/src/main/resources/default.config
@@ -318,11 +318,11 @@
             "to": "androidx/core/content/res/GrowingArrayUtils{0}"
         },
 
-	{
+        {
             "from": "android/support/v4/content/res/ColorStateListInflaterCompat(.*)",
             "to": "androidx/core/content/res/ColorStateListInflaterCompat{0}"
         },
-	{
+        {
             "from": "android/support/v7/content/res/AppCompatColorStateListInflater(.*)",
             "to": "androidx/core/content/res/ColorStateListInflaterCompat{0}"
         },
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index c0471a6..d585d2e 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -441,6 +441,10 @@
       "to": "ignore"
     },
     {
+      "from": "androidx/tracing/(.*)",
+      "to": "ignore"
+    },
+    {
       "from": "androidx/fragment/app/DefaultSpecialEffectsController(.*)",
       "to": "android/support/v4/app/DefaultSpecialEffectsController{0}"
     },
diff --git a/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java b/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
index d7ed4e1..cb7620b 100644
--- a/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
+++ b/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
@@ -25,6 +25,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.ReportFragment.ActivityInitializationListener;
 
@@ -159,6 +160,7 @@
         mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
         Application app = (Application) context.getApplicationContext();
         app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
+            @RequiresApi(29)
             @Override
             public void onActivityPreCreated(@NonNull Activity activity,
                     @Nullable Bundle savedInstanceState) {
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
index 84b030d..3c0857f 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
@@ -30,7 +30,7 @@
  * It also handles the communication of the Activity / Fragment with the rest of the application
  * (e.g. calling the business logic classes).
  * <p>
- * A ViewModel is always created in association with a scope (an fragment or an activity) and will
+ * A ViewModel is always created in association with a scope (a fragment or an activity) and will
  * be retained as long as the scope is alive. E.g. if it is an Activity, until it is
  * finished.
  * <p>
diff --git a/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
index 87642ca..29721da 100644
--- a/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
+++ b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
@@ -17,6 +17,7 @@
 package com.example.android.appcompat;
 
 import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.widget.TextView;
 
@@ -49,5 +50,8 @@
         ColorStateList csl2 = new ResourceLoader().getColorStateList(
                 R.color.color_state_list_missing_android_alpha);
         dummy.setTextColor(csl2);
+
+        Drawable dr = getResources().getDrawable(R.drawable.app_sample_code);
+        dummy.setCompoundDrawables(dr, null, null, null);
     }
 }
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
index 2645d54..7223b1a 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
@@ -98,9 +98,7 @@
     protected fun navigate() {
         Log.i(TAG, "navigate: ")
         val installMonitor = DynamicInstallMonitor()
-        val extras = DynamicExtras.Builder()
-            .setInstallMonitor(installMonitor)
-            .build()
+        val extras = DynamicExtras(installMonitor)
         findNavController().navigate(destinationId, destinationArgs, null, extras)
         if (!installMonitor.isInstallRequired) {
             Log.i(TAG, "navigate: install not required")
diff --git a/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/current.txt b/navigation/navigation-dynamic-features-runtime/api/current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/current.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
@@ -15,17 +15,13 @@
   }
 
   public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+    ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+    ctor public DynamicExtras();
     method public androidx.navigation.Navigator.Extras? getDestinationExtras();
     method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
   }
 
-  public static final class DynamicExtras.Builder {
-    ctor public DynamicExtras.Builder();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras build();
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
-    method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
-  }
-
   @androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
     ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
     method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/build.gradle b/navigation/navigation-dynamic-features-runtime/build.gradle
index 58e3624..593f64a 100644
--- a/navigation/navigation-dynamic-features-runtime/build.gradle
+++ b/navigation/navigation-dynamic-features-runtime/build.gradle
@@ -28,7 +28,7 @@
 
 dependencies {
     api(project(":navigation:navigation-runtime-ktx"))
-    api("com.google.android.play:core:1.6.4")
+    api("com.google.android.play:core:1.6.5")
     api(KOTLIN_STDLIB)
 
     testImplementation(ANDROIDX_TEST_CORE)
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
index c949aa0..1e5a09d 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
@@ -21,56 +21,16 @@
 /**
  * Extras for dynamic navigators.
  *
- * You can set a [DynamicInstallMonitor] here to be notified of install state changes.
+ * You can set a [DynamicInstallMonitor] here to be notified of install state changes as well as any
+ * [Navigator.Extras].
  */
-class DynamicExtras internal constructor(
+class DynamicExtras @JvmOverloads constructor(
     /**
      * @return The [DynamicInstallMonitor] used.
      */
-    val installMonitor: DynamicInstallMonitor?,
+    val installMonitor: DynamicInstallMonitor? = null,
     /**
      * @return [Navigator.Extras] associated with these [DynamicExtras].
      */
-    val destinationExtras: Navigator.Extras?
-) : Navigator.Extras {
-
-    /**
-     * Builder that enables creation of [DynamicExtras].
-     */
-    class Builder {
-
-        private var monitor: DynamicInstallMonitor? = null
-        private var destinationExtras: Navigator.Extras? = null
-
-        /**
-         * Set the [DynamicInstallMonitor].
-         *
-         * @param monitor The [DynamicInstallMonitor] to set.
-         * @return This [Builder].
-         */
-        fun setInstallMonitor(monitor: DynamicInstallMonitor): Builder {
-            this.monitor = monitor
-            return this
-        }
-
-        /**
-         * Set the [Navigator.Extras].
-         *
-         * @param destinationExtras The [Navigator.Extras] to set.
-         * @return This [Builder].
-         */
-        fun setDestinationExtras(destinationExtras: Navigator.Extras): Builder {
-            this.destinationExtras = destinationExtras
-            return this
-        }
-
-        /**
-         * Build [DynamicExtras].
-         *
-         * @return A new instance of [DynamicExtras] with all attributes set in the builder.
-         */
-        fun build(): DynamicExtras {
-            return DynamicExtras(monitor, destinationExtras)
-        }
-    }
-}
+    val destinationExtras: Navigator.Extras? = null
+) : Navigator.Extras
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
index 9161689..7a9dc0e 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
@@ -33,17 +33,14 @@
     fun build_withMonitorAndExtras() {
         val monitor = DynamicInstallMonitor()
         val navExtras = TestNavigatorExtras()
-        val builder = DynamicExtras.Builder()
-            .setInstallMonitor(monitor)
-            .setDestinationExtras(navExtras)
-        val extras = builder.build()
+        val extras = DynamicExtras(monitor, navExtras)
         assertThat(extras.destinationExtras).isNotNull()
         assertThat(extras.installMonitor).isNotNull()
     }
 
     @Test
     fun build_withoutMonitorOrExtras() {
-        val extras = DynamicExtras.Builder().build()
+        val extras = DynamicExtras()
         assertThat(extras.destinationExtras).isNull()
         assertThat(extras.installMonitor).isNull()
     }
diff --git a/paging/common/api/3.0.0-alpha01.txt b/paging/common/api/3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/3.0.0-alpha01.txt
+++ b/paging/common/api/3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/current.txt
+++ b/paging/common/api/current.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
+++ b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/api/public_plus_experimental_current.txt b/paging/common/api/public_plus_experimental_current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/public_plus_experimental_current.txt
+++ b/paging/common/api/public_plus_experimental_current.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/api/restricted_3.0.0-alpha01.txt b/paging/common/api/restricted_3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/restricted_3.0.0-alpha01.txt
+++ b/paging/common/api/restricted_3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/api/restricted_current.txt b/paging/common/api/restricted_current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/restricted_current.txt
+++ b/paging/common/api/restricted_current.txt
@@ -253,13 +253,14 @@
     method public static <T> androidx.paging.PagingData<T> empty();
     method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
-    method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
     field public static final androidx.paging.PagingData.Companion! Companion;
   }
 
   public static final class PagingData.Companion {
     method public <T> androidx.paging.PagingData<T> empty();
+    method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
   }
 
   public final class PagingDataFlow {
@@ -267,6 +268,10 @@
     method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
   }
 
+  public final class PagingDataKt {
+    method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
   public abstract class PagingSource<Key, Value> {
     ctor public PagingSource();
     method public final boolean getInvalid();
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingData.kt b/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
index 50024228..73a92e4 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
@@ -61,22 +61,6 @@
     fun filter(predicate: (T) -> Boolean): PagingData<T> = transform { it.filter(predicate) }
 
     /**
-     * Returns a [PagingData] containing each original element, with an optional separator generated
-     * by [generator], given the elements before and after (or null, in boundary conditions).
-     *
-     * Note that this transform is applied asynchronously, as pages are loaded. Potential
-     * separators between pages are only computed once both pages are loaded.
-     *
-     * @sample androidx.paging.samples.insertSeparatorsSample
-     */
-    fun <R : T> insertSeparators(
-        generator: (T?, T?) -> R?
-    ) = PagingData(
-        flow = flow.insertSeparators(generator),
-        receiver = receiver
-    )
-
-    /**
      * Returns a [PagingData] containing each original element, with the passed header [item] added
      * to the start of the list.
      *
@@ -128,11 +112,129 @@
         @Suppress("UNCHECKED_CAST", "SyntheticAccessor")
         @JvmStatic // Convenience for Java developers.
         fun <T : Any> empty() = EMPTY as PagingData<T>
+
+        // NOTE: samples in the doc below are manually imported from Java code in the samples
+        // project, since Java cannot be linked with @sample.
+        // DO NOT CHANGE THE BELOW COMMENT WITHOUT MAKING THE CORRESPONDING CHANGE IN `samples/`
+        /**
+         * Returns a [PagingData] containing each original element, with an optional separator
+         * generated by [generator], given the elements before and after (or null, in boundary
+         * conditions).
+         *
+         * Note that this transform is applied asynchronously, as pages are loaded. Potential
+         * separators between pages are only computed once both pages are loaded.
+         *
+         * **Kotlin callers should instead use the extension function [insertSeparators]**
+         *
+         * ```
+         * /*
+         *  * Create letter separators in an alphabetically sorted list.
+         *  *
+         *  * For example, if the input is:
+         *  *     "apple", "apricot", "banana", "carrot"
+         *  *
+         *  * The operator would output:
+         *  *     "A", "apple", "apricot", "B", "banana", "C", "carrot"
+         *  */
+         * pagingData = PagingData.insertSeparators(pagingData,
+         *         (@Nullable String before, @Nullable String after) -> {
+         *             if (after != null && (before == null
+         *                     || before.charAt(0) != after.charAt(0))) {
+         *                 // separator - after is first item that starts with its first letter
+         *                 return Character.toString(Character.toUpperCase(after.charAt(0)));
+         *             } else {
+         *                 // no separator - either end of list, or first letters of before/after
+         *                 // are the same
+         *                 return null;
+         *              }
+         *          });
+         *
+         * /*
+         *  * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+         *  *
+         *  * For example, if the input is (each an `Item`):
+         *  *     "apple", "apricot", "banana", "carrot"
+         *  *
+         *  * The operator would output a list of UiModels corresponding to:
+         *  *     "A", "apple", "apricot", "B", "banana", "C", "carrot"
+         *  */
+         * // first convert items in stream to UiModel.Item
+         * PagingData<UiModel.ItemModel> itemModelPagingData =
+         *         itemPagingData.map(UiModel.ItemModel::new);
+         *
+         * // Now insert UiModel.Separators, which makes the PagingData of generic type UiModel
+         * PagingData<UiModel> pagingDataWithSeparators = PagingData.insertSeparators(
+         *         itemModelPagingData,
+         *         (@Nullable UiModel.ItemModel before, @Nullable UiModel.ItemModel after) -> {
+         *             if (after != null
+         *                     && (before == null
+         *                     || before.item.label.charAt(0) != after.item.label.charAt(0))) {
+         *                 // separator - after is first item that starts with its first letter
+         *                 return new UiModel.SeparatorModel(
+         *                         Character.toUpperCase(after.item.label.charAt(0)));
+         *             } else {
+         *                 // no separator - either end of list, or first letters of items are the same
+         *                 return null;
+         *             }
+         *         });
+         *
+         *
+         * public class UiModel {
+         *     static class ItemModel extends UiModel {
+         *         public Item item;
+         *         ItemModel(Item item) {
+         *             this.item = item;
+         *         }
+         *     }
+         *     static class SeparatorModel extends UiModel {
+         *         public char character;
+         *         SeparatorModel(char character) {
+         *             this.character = character;
+         *         }
+         *     }
+         * }
+         */
+        @JvmStatic
+        fun <T : R, R : Any> insertSeparators(
+            pagingData: PagingData<T>,
+            generator: (T?, T?) -> R?
+        ): PagingData<R> {
+            return pagingData.insertSeparators(generator)
+        }
     }
 }
 
+/**
+ * Returns a [PagingData] containing each original element, with an optional separator
+ * generated by [generator], given the elements before and after (or null, in boundary
+ * conditions).
+ *
+ * Note that this transform is applied asynchronously, as pages are loaded. Potential
+ * separators between pages are only computed once both pages are loaded.
+ *
+ * **Java callers should instead use the static function [PagingData.insertSeparators]**
+ *
+ * @sample androidx.paging.samples.insertSeparatorsSample
+ * @sample androidx.paging.samples.insertSeparatorsUiModelSample
+ */
+fun <T : R, R : Any> PagingData<T>.insertSeparators(
+    generator: (T?, T?) -> R?
+): PagingData<R> {
+    // This function must be an extension method, as it indirectly imposes a constraint on
+    // the type of T (because T extends R). Ideally it would be declared not be an
+    // extension, to make this method discoverable for Java callers, but we need to support
+    // the common UI model pattern for separators:
+    //     class UiModel
+    //     class ItemModel: UiModel
+    //     class SeparatorModel: UiModel
+    return PagingData(
+        flow = flow.insertSeparators(generator),
+        receiver = receiver
+    )
+}
+
 internal interface UiReceiver {
     fun addHint(hint: ViewportHint)
     fun retry()
     fun refresh()
-}
\ No newline at end of file
+}
diff --git a/paging/common/src/main/kotlin/androidx/paging/Separators.kt b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
index 2c6a803..bb645a4 100644
--- a/paging/common/src/main/kotlin/androidx/paging/Separators.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
@@ -359,7 +359,7 @@
     }
 }
 
-internal fun <R : Any, T : R> Flow<PageEvent<T>>.insertSeparators(
+internal fun <T : R, R : Any> Flow<PageEvent<T>>.insertSeparators(
     generator: (T?, T?) -> R?
 ): Flow<PageEvent<R>> {
     val separatorState = SeparatorState(generator)
diff --git a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
index 41fb019..04fb0ed 100644
--- a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
@@ -596,6 +596,43 @@
         )
     }
 
+    @Test
+    fun types() = runBlockingTest {
+        open class Base
+        data class PrimaryType(val string: String) : Base()
+        data class SeparatorType(val string: String) : Base()
+
+        assertInsertData(
+            listOf(
+                Refresh(
+                    pages = listOf(
+                        listOf(
+                            PrimaryType("a1"),
+                            SeparatorType("B"),
+                            PrimaryType("b1")
+                        )
+                    ).toTransformablePages(),
+                    placeholdersStart = 0,
+                    placeholdersEnd = 1,
+                    loadStates = mapOf(REFRESH to Idle, START to Idle, END to Idle)
+                )
+            ),
+            flowOf(
+                Refresh(
+                    pages = listOf(listOf(PrimaryType("a1"), PrimaryType("b1")))
+                        .toTransformablePages(),
+                    placeholdersStart = 0,
+                    placeholdersEnd = 1,
+                    loadStates = mapOf(REFRESH to Idle, START to Idle, END to Idle)
+                )
+            ).insertSeparators<PrimaryType, Base> { before, after ->
+                return@insertSeparators (if (before != null && after != null) {
+                    SeparatorType("B")
+                } else null)
+            }.toList()
+        )
+    }
+
     companion object {
         /**
          * Creates an upper-case letter at the beginning of each section of strings that start
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
index dd1cffb..0954001 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
@@ -22,6 +22,7 @@
 import androidx.paging.PagingConfig
 import androidx.paging.PagingDataFlow
 import androidx.paging.cachedIn
+import androidx.paging.insertSeparators
 import kotlinx.coroutines.flow.map
 
 class V3ViewModel : ViewModel() {
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
index c6ba658..3f3ec1b 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
@@ -24,6 +24,7 @@
 import androidx.paging.PagingConfig
 import androidx.paging.PagingDataFlow
 import androidx.paging.cachedIn
+import androidx.paging.insertSeparators
 import androidx.paging.integration.testapp.room.Customer
 import androidx.paging.integration.testapp.room.SampleDatabase
 import androidx.room.Room
diff --git a/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt b/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
index 27fdbf6..9ffd45a 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
@@ -18,6 +18,7 @@
 
 package androidx.paging.samples
 
+import android.annotation.SuppressLint
 import android.os.Bundle
 import androidx.activity.viewModels
 import androidx.annotation.Sampled
@@ -34,13 +35,14 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
 
-internal class UiModel(@Suppress("UNUSED_PARAMETER") string: String)
-internal class MyPagingAdapter : BasePagingAdapter<UiModel>()
-internal class MyViewModel : BaseViewModel<UiModel>()
-lateinit var pagingSourceFactory: () -> PagingSource<String, String>
+private class UiModel(@Suppress("UNUSED_PARAMETER") string: String)
+private class MyPagingAdapter : BasePagingAdapter<UiModel>()
+private class MyViewModel : BaseViewModel<UiModel>()
+private lateinit var pagingSourceFactory: () -> PagingSource<String, String>
 
 @ExperimentalCoroutinesApi
 @Sampled
+@SuppressLint("SyntheticAccessor")
 fun cachedInSample() {
     class MyViewModel : ViewModel() {
         val flow = PagingDataFlow(PagingConfig(pageSize = 40), pagingSourceFactory)
diff --git a/paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
similarity index 94%
rename from paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt
rename to paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
index 061284d..8016bc3 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
@@ -20,8 +20,9 @@
 
 import androidx.annotation.Sampled
 import androidx.paging.PagingData
+import androidx.paging.insertSeparators
 
-lateinit var pagingData: PagingData<String>
+private lateinit var pagingData: PagingData<String>
 
 @Sampled
 fun insertSeparatorsSample() {
diff --git a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
new file mode 100644
index 0000000..5a85638
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+@file:Suppress("unused") // Currently, all samples incorrectly labeled as unused.
+
+package androidx.paging.samples
+
+import androidx.annotation.Sampled
+import androidx.paging.PagingData
+import androidx.paging.insertSeparators
+
+class Item(
+    @JvmField
+    val label: String
+)
+
+private lateinit var pagingData: PagingData<Item>
+
+@Sampled
+fun insertSeparatorsUiModelSample() {
+    open class UiModel
+    data class ItemUiModel(val item: Item) : UiModel()
+    data class SeparatorUiModel(val char: Char) : UiModel()
+
+    /*
+     * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+     *
+     * For example, if the input is (each an `Item`):
+     *     "apple", "apricot", "banana", "carrot"
+     *
+     * The operator would output a list of UiModels corresponding to:
+     *     "A", "apple", "apricot", "B", "banana", "C", "carrot"
+     */
+    pagingData
+        .map { item ->
+            ItemUiModel(item) // convert items in stream to ItemUiModel
+        }
+        .insertSeparators<ItemUiModel, UiModel> { before: ItemUiModel?, after: ItemUiModel? ->
+            if (after != null && before?.item?.label?.first() != after.item.label.first()) {
+                // separator - after is first item that starts with its first letter
+                SeparatorUiModel(after.item.label.first().toUpperCase())
+            } else {
+                // no separator - either end of list, or first letters of before/after are the same
+                null
+            }
+        }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java
new file mode 100644
index 0000000..7e5d9f8
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java
@@ -0,0 +1,58 @@
+/*
+ * 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.paging.samples.java;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.paging.PagingData;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+class InsertSeparatorsJavaSample {
+    @NonNull
+    public PagingData<String> pagingData = PagingData.empty();
+
+    @SuppressWarnings("unused")
+    public void insertSeparatorsSample() {
+        /*
+         * Create letter separators in an alphabetically sorted list.
+         *
+         * For example, if the input is:
+         *     "apple", "apricot", "banana", "carrot"
+         *
+         * The operator would output:
+         *     "A", "apple", "apricot", "B", "banana", "C", "carrot"
+         */
+        pagingData = PagingData.insertSeparators(pagingData,
+                (@Nullable String before, @Nullable String after) -> {
+                    if (after != null && (before == null
+                            || before.charAt(0) != after.charAt(0))) {
+                        // separator - after is first item that starts with its first letter
+                        return Character.toString(Character.toUpperCase(after.charAt(0)));
+                    } else {
+                        // no separator - either end of list, or first letters of before/after
+                        // are the same
+                        return null;
+                    }
+                });
+    }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java
new file mode 100644
index 0000000..54a9c14
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java
@@ -0,0 +1,65 @@
+/*
+ * 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.paging.samples.java;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.paging.PagingData;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+class InsertSeparatorsJavaUiModelSample {
+    @NonNull
+    public PagingData<Item> itemPagingData = PagingData.empty();
+
+    @SuppressWarnings("unused")
+    public void insertSeparatorsSample() {
+        /*
+         * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+         *
+         * For example, if the input is (each an `Item`):
+         *     "apple", "apricot", "banana", "carrot"
+         *
+         * The operator would output a list of UiModels corresponding to:
+         *     "A", "apple", "apricot", "B", "banana", "C", "carrot"
+         */
+        // first convert items in stream to UiModel.Item
+        PagingData<UiModel.ItemModel> itemModelPagingData =
+                itemPagingData.map(UiModel.ItemModel::new);
+
+        // Now insert UiModel.Separators, which makes the PagingData of generic type UiModel
+        PagingData<UiModel> pagingDataWithSeparators = PagingData.insertSeparators(
+                itemModelPagingData,
+                (@Nullable UiModel.ItemModel before, @Nullable UiModel.ItemModel after) -> {
+                    if (after != null
+                            && (before == null
+                            || before.item.label.charAt(0) != after.item.label.charAt(0))) {
+                        // separator - after is first item that starts with its first letter
+                        return new UiModel.SeparatorModel(
+                                Character.toUpperCase(after.item.label.charAt(0)));
+                    } else {
+                        // no separator - either end of list, or first letters of items are the same
+                        return null;
+                    }
+                });
+    }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/Item.java b/paging/samples/src/main/java/androidx/paging/samples/java/Item.java
new file mode 100644
index 0000000..44b9485
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/Item.java
@@ -0,0 +1,22 @@
+/*
+ * 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.paging.samples.java;
+
+class Item {
+    @SuppressWarnings("WeakerAccess")
+    public String label;
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java b/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java
new file mode 100644
index 0000000..2562c72
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java
@@ -0,0 +1,43 @@
+/*
+ * 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.paging.samples.java;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class UiModel {
+    public UiModel() {}
+
+    static class ItemModel extends UiModel {
+        public Item item;
+
+        ItemModel(Item item) {
+            this.item = item;
+        }
+    }
+
+    static class SeparatorModel extends UiModel {
+        public char character;
+        SeparatorModel(char character) {
+            this.character = character;
+        }
+    }
+}
diff --git a/recyclerview/recyclerview/build.gradle b/recyclerview/recyclerview/build.gradle
index 5ae4a86..3c03669 100644
--- a/recyclerview/recyclerview/build.gradle
+++ b/recyclerview/recyclerview/build.gradle
@@ -31,6 +31,7 @@
 
     testImplementation(JUNIT)
     testImplementation(MOCKITO_CORE)
+    testImplementation(KOTLIN_STDLIB)
     lintPublish(project(':recyclerview:recyclerview-lint'))
 }
 
diff --git a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java
deleted file mode 100644
index 2262294..0000000
--- a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright 2018 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.recyclerview.widget;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-
-import androidx.annotation.Nullable;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-
-@RunWith(JUnit4.class)
-public class DiffUtilTest {
-    private static Random sRand = new Random(System.nanoTime());
-    private List<Item> mBefore = new ArrayList<>();
-    private List<Item> mAfter = new ArrayList<>();
-    private StringBuilder mLog = new StringBuilder();
-
-    private DiffUtil.Callback mCallback = new DiffUtil.Callback() {
-        @Override
-        public int getOldListSize() {
-            return mBefore.size();
-        }
-
-        @Override
-        public int getNewListSize() {
-            return mAfter.size();
-        }
-
-        @Override
-        public boolean areItemsTheSame(int oldItemIndex, int newItemIndex) {
-            return mBefore.get(oldItemIndex).id == mAfter.get(newItemIndex).id;
-        }
-
-        @Override
-        public boolean areContentsTheSame(int oldItemIndex, int newItemIndex) {
-            assertThat(mBefore.get(oldItemIndex).id,
-                    CoreMatchers.equalTo(mAfter.get(newItemIndex).id));
-            return mBefore.get(oldItemIndex).data.equals(mAfter.get(newItemIndex).data);
-        }
-
-        @Nullable
-        @Override
-        public Object getChangePayload(int oldItemIndex, int newItemIndex) {
-            assertThat(mBefore.get(oldItemIndex).id,
-                    CoreMatchers.equalTo(mAfter.get(newItemIndex).id));
-            assertThat(mBefore.get(oldItemIndex).data,
-                    not(CoreMatchers.equalTo(mAfter.get(newItemIndex).data)));
-            return mAfter.get(newItemIndex).payload;
-        }
-    };
-
-    @Rule
-    public TestWatcher mLogOnExceptionWatcher = new TestWatcher() {
-        @Override
-        protected void failed(Throwable e, Description description) {
-            System.err.println(mLog.toString());
-        }
-    };
-
-
-    @Test
-    public void testNoChange() {
-        initWithSize(5);
-        check();
-    }
-
-    @Test
-    public void testAddItems() {
-        initWithSize(2);
-        add(1);
-        check();
-    }
-
-    //@Test
-    //@LargeTest
-    // Used for development
-    public void testRandom() {
-        for (int x = 0; x < 100; x++) {
-            for (int i = 0; i < 100; i++) {
-                for (int j = 2; j < 40; j++) {
-                    testRandom(i, j);
-                }
-            }
-        }
-    }
-
-    @Test
-    public void testGen2() {
-        initWithSize(5);
-        add(5);
-        delete(3);
-        delete(1);
-        check();
-    }
-
-    @Test
-    public void testGen3() {
-        initWithSize(5);
-        add(0);
-        delete(1);
-        delete(3);
-        check();
-    }
-
-    @Test
-    public void testGen4() {
-        initWithSize(5);
-        add(5);
-        add(1);
-        add(4);
-        add(4);
-        check();
-    }
-
-    @Test
-    public void testGen5() {
-        initWithSize(5);
-        delete(0);
-        delete(2);
-        add(0);
-        add(2);
-        check();
-    }
-
-    @Test
-    public void testGen6() {
-        initWithSize(2);
-        delete(0);
-        delete(0);
-        check();
-    }
-
-    @Test
-    public void testGen7() {
-        initWithSize(3);
-        move(2, 0);
-        delete(2);
-        add(2);
-        check();
-    }
-
-    @Test
-    public void testGen8() {
-        initWithSize(3);
-        delete(1);
-        add(0);
-        move(2, 0);
-        check();
-    }
-
-    @Test
-    public void testGen9() {
-        initWithSize(2);
-        add(2);
-        move(0, 2);
-        check();
-    }
-
-    @Test
-    public void testGen10() {
-        initWithSize(3);
-        move(0, 1);
-        move(1, 2);
-        add(0);
-        check();
-    }
-
-    @Test
-    public void testGen11() {
-        initWithSize(4);
-        move(2, 0);
-        move(2, 3);
-        check();
-    }
-
-    @Test
-    public void testGen12() {
-        initWithSize(4);
-        move(3, 0);
-        move(2, 1);
-        check();
-    }
-
-    @Test
-    public void testGen13() {
-        initWithSize(4);
-        move(3, 2);
-        move(0, 3);
-        check();
-    }
-
-    @Test
-    public void testGen14() {
-        initWithSize(4);
-        move(3, 2);
-        add(4);
-        move(0, 4);
-        check();
-    }
-
-    @Test
-    public void testAdd1() {
-        initWithSize(1);
-        add(1);
-        check();
-    }
-
-    @Test
-    public void testMove1() {
-        initWithSize(3);
-        move(0, 2);
-        check();
-    }
-
-    @Test
-    public void tmp() {
-        initWithSize(4);
-        move(0, 2);
-        check();
-    }
-
-    @Test
-    public void testUpdate1() {
-        initWithSize(3);
-        update(2);
-        check();
-    }
-
-    @Test
-    public void testUpdate2() {
-        initWithSize(2);
-        add(1);
-        update(1);
-        update(2);
-        check();
-    }
-
-    @Test
-    public void testDisableMoveDetection() {
-        initWithSize(5);
-        move(0, 4);
-        List<Item> applied = applyUpdates(mBefore, DiffUtil.calculateDiff(mCallback, false));
-        assertThat(applied.size(), is(5));
-        assertThat(applied.get(4).newItem, is(true));
-        assertThat(applied.contains(mBefore.get(0)), is(false));
-    }
-
-    @Test(expected = IndexOutOfBoundsException.class)
-    public void convertOldPositionToNew_tooSmall() {
-        initWithSize(2);
-        update(2);
-        DiffUtil.calculateDiff(mCallback).convertOldPositionToNew(-1);
-    }
-
-    @Test(expected = IndexOutOfBoundsException.class)
-    public void convertOldPositionToNew_tooLarge() {
-        initWithSize(2);
-        update(2);
-        DiffUtil.calculateDiff(mCallback).convertOldPositionToNew(2);
-    }
-
-    @Test(expected = IndexOutOfBoundsException.class)
-    public void convertNewPositionToOld_tooSmall() {
-        initWithSize(2);
-        update(2);
-        DiffUtil.calculateDiff(mCallback).convertNewPositionToOld(-1);
-    }
-
-    @Test(expected = IndexOutOfBoundsException.class)
-    public void convertNewPositionToOld_tooLarge() {
-        initWithSize(2);
-        update(2);
-        DiffUtil.calculateDiff(mCallback).convertNewPositionToOld(2);
-    }
-
-    private void testRandom(int initialSize, int operationCount) {
-        mLog.setLength(0);
-        initWithSize(initialSize);
-        for (int i = 0; i < operationCount; i++) {
-            int op = sRand.nextInt(5);
-            switch (op) {
-                case 0:
-                    add(sRand.nextInt(mAfter.size() + 1));
-                    break;
-                case 1:
-                    if (!mAfter.isEmpty()) {
-                        delete(sRand.nextInt(mAfter.size()));
-                    }
-                    break;
-                case 2:
-                    // move
-                    if (mAfter.size() > 0) {
-                        move(sRand.nextInt(mAfter.size()), sRand.nextInt(mAfter.size()));
-                    }
-                    break;
-                case 3:
-                    // update
-                    if (mAfter.size() > 0) {
-                        update(sRand.nextInt(mAfter.size()));
-                    }
-                    break;
-                case 4:
-                    // update with payload
-                    if (mAfter.size() > 0) {
-                        updateWithPayload(sRand.nextInt(mAfter.size()));
-                    }
-                    break;
-            }
-        }
-        check();
-    }
-
-    private void check() {
-        DiffUtil.DiffResult result = DiffUtil.calculateDiff(mCallback);
-        log("before", mBefore);
-        log("after", mAfter);
-        log("snakes", result.getSnakes());
-
-        // test diff dispatch
-        List<Item> applied = applyUpdates(mBefore, result);
-        assertEquals(applied, mAfter);
-
-        // test position conversion
-        for (int oldPos = 0; oldPos < mBefore.size(); oldPos++) {
-            int newPos = result.convertOldPositionToNew(oldPos);
-            if (newPos != DiffUtil.DiffResult.NO_POSITION) {
-                Assert.assertEquals(mBefore.get(oldPos).id, mAfter.get(newPos).id);
-            } else {
-                assertFalse(mAfter.contains(mBefore.get(oldPos)));
-            }
-        }
-
-        try {
-            result.convertOldPositionToNew(mBefore.size());
-            fail("out of bounds should occur");
-        } catch (IndexOutOfBoundsException e) {
-            // expected
-        }
-        for (int newPos = 0; newPos < mAfter.size(); newPos++) {
-            int oldPos = result.convertNewPositionToOld(newPos);
-            if (oldPos != DiffUtil.DiffResult.NO_POSITION) {
-                Assert.assertEquals(mAfter.get(newPos).id, mBefore.get(oldPos).id);
-            } else {
-                assertFalse(mBefore.contains(mAfter.get(newPos)));
-            }
-        }
-        try {
-            result.convertNewPositionToOld(mAfter.size());
-            fail("out of bounds should occur");
-        } catch (IndexOutOfBoundsException e) {
-            // expected
-        }
-    }
-
-    private void initWithSize(int size) {
-        mBefore.clear();
-        mAfter.clear();
-        for (int i = 0; i < size; i++) {
-            mBefore.add(new Item(false));
-        }
-        mAfter.addAll(mBefore);
-        mLog.append("initWithSize(" + size + ");\n");
-    }
-
-    private void log(String title, List<?> items) {
-        mLog.append(title).append(":").append(items.size()).append("\n");
-        for (Object item : items) {
-            mLog.append("  ").append(item).append("\n");
-        }
-    }
-
-    private void assertEquals(List<Item> applied, List<Item> after) {
-        log("applied", applied);
-
-        String report = mLog.toString();
-        assertThat(report, applied.size(), is(after.size()));
-        for (int i = 0; i < after.size(); i++) {
-            Item item = applied.get(i);
-            if (after.get(i).newItem) {
-                assertThat(report, item.newItem, is(true));
-            } else if (after.get(i).changed) {
-                assertThat(report, item.newItem, is(false));
-                assertThat(report, item.changed, is(true));
-                assertThat(report, item.id, is(after.get(i).id));
-                assertThat(report, item.payload, is(after.get(i).payload));
-            } else {
-                assertThat(report, item, equalTo(after.get(i)));
-            }
-        }
-    }
-
-    private List<Item> applyUpdates(List<Item> before, DiffUtil.DiffResult result) {
-        final List<Item> target = new ArrayList<>();
-        target.addAll(before);
-        result.dispatchUpdatesTo(new ListUpdateCallback() {
-            @Override
-            public void onInserted(int position, int count) {
-                for (int i = 0; i < count; i++) {
-                    target.add(i + position, new Item(true));
-                }
-            }
-
-            @Override
-            public void onRemoved(int position, int count) {
-                for (int i = 0; i < count; i++) {
-                    target.remove(position);
-                }
-            }
-
-            @Override
-            public void onMoved(int fromPosition, int toPosition) {
-                Item item = target.remove(fromPosition);
-                target.add(toPosition, item);
-            }
-
-            @Override
-            public void onChanged(int position, int count, Object payload) {
-                for (int i = 0; i < count; i++) {
-                    int positionInList = position + i;
-                    Item existing = target.get(positionInList);
-                    // make sure we don't update same item twice in callbacks
-                    assertThat(existing.changed, is(false));
-                    assertThat(existing.newItem, is(false));
-                    assertThat(existing.payload, is(nullValue()));
-                    Item replica = new Item(existing);
-                    replica.payload = (String) payload;
-                    replica.changed = true;
-                    target.remove(positionInList);
-                    target.add(positionInList, replica);
-                }
-            }
-        });
-        return target;
-    }
-
-    private void add(int index) {
-        mAfter.add(index, new Item(true));
-        mLog.append("add(").append(index).append(");\n");
-    }
-
-    private void delete(int index) {
-        mAfter.remove(index);
-        mLog.append("delete(").append(index).append(");\n");
-    }
-
-    private void update(int index) {
-        Item existing = mAfter.get(index);
-        if (existing.newItem) {
-            return;//new item cannot be changed
-        }
-        Item replica = new Item(existing);
-        replica.changed = true;
-        // clean the payload since this might be after an updateWithPayload call
-        replica.payload = null;
-        replica.data = UUID.randomUUID().toString();
-        mAfter.remove(index);
-        mAfter.add(index, replica);
-        mLog.append("update(").append(index).append(");\n");
-    }
-
-    private void updateWithPayload(int index) {
-        Item existing = mAfter.get(index);
-        if (existing.newItem) {
-            return;//new item cannot be changed
-        }
-        Item replica = new Item(existing);
-        replica.changed = true;
-        replica.data = UUID.randomUUID().toString();
-        replica.payload = UUID.randomUUID().toString();
-        mAfter.remove(index);
-        mAfter.add(index, replica);
-        mLog.append("update(").append(index).append(");\n");
-    }
-
-    private void move(int from, int to) {
-        Item removed = mAfter.remove(from);
-        mAfter.add(to, removed);
-        mLog.append("move(").append(from).append(",").append(to).append(");\n");
-    }
-
-    static class Item {
-        static long idCounter = 0;
-        final long id;
-        final boolean newItem;
-        boolean changed = false;
-        String payload;
-
-        String data = UUID.randomUUID().toString();
-
-        public Item(boolean newItem) {
-            id = idCounter++;
-            this.newItem = newItem;
-        }
-
-        public Item(Item other) {
-            id = other.id;
-            newItem = other.newItem;
-            changed = other.changed;
-            payload = other.payload;
-            data = other.data;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Item item = (Item) o;
-
-            if (id != item.id) return false;
-            if (newItem != item.newItem) return false;
-            if (changed != item.changed) return false;
-            if (payload != null ? !payload.equals(item.payload) : item.payload != null) {
-                return false;
-            }
-            return data.equals(item.data);
-
-        }
-
-        @Override
-        public int hashCode() {
-            int result = (int) (id ^ (id >>> 32));
-            result = 31 * result + (newItem ? 1 : 0);
-            result = 31 * result + (changed ? 1 : 0);
-            result = 31 * result + (payload != null ? payload.hashCode() : 0);
-            result = 31 * result + data.hashCode();
-            return result;
-        }
-
-        @Override
-        public String toString() {
-            return "Item{" +
-                    "id=" + id +
-                    ", newItem=" + newItem +
-                    ", changed=" + changed +
-                    ", payload='" + payload + '\'' +
-                    ", data='" + data + '\'' +
-                    '}';
-        }
-    }
-}
diff --git a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
new file mode 100644
index 0000000..dea8900
--- /dev/null
+++ b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2018 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.recyclerview.widget
+
+import org.hamcrest.CoreMatchers.`is`
+import org.hamcrest.CoreMatchers.equalTo
+import org.hamcrest.CoreMatchers.not
+import org.hamcrest.CoreMatchers.nullValue
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import java.util.Random
+import java.util.UUID
+
+@RunWith(JUnit4::class)
+class DiffUtilTest {
+    private val before = mutableListOf<Item>()
+    private val after = mutableListOf<Item>()
+    private val log = StringBuilder()
+    private val callback: DiffUtil.Callback =
+        object : DiffUtil.Callback() {
+            override fun getOldListSize() = before.size
+
+            override fun getNewListSize() = after.size
+
+            override fun areItemsTheSame(
+                oldItemIndex: Int,
+                newItemIndex: Int
+            ): Boolean {
+                return before[oldItemIndex].id == after[newItemIndex].id
+            }
+
+            override fun areContentsTheSame(
+                oldItemIndex: Int,
+                newItemIndex: Int
+            ): Boolean {
+                assertThat(
+                    before[oldItemIndex].id,
+                    equalTo(after[newItemIndex].id)
+                )
+                return before[oldItemIndex].data == after[newItemIndex].data
+            }
+
+            override fun getChangePayload(
+                oldItemIndex: Int,
+                newItemIndex: Int
+            ): Any? {
+                assertThat(
+                    before[oldItemIndex].id,
+                    equalTo(after[newItemIndex].id)
+                )
+                assertThat(
+                    before[oldItemIndex].data,
+                    not(
+                        equalTo(
+                            after[newItemIndex].data
+                        )
+                    )
+                )
+                return after[newItemIndex].payload
+            }
+        }
+
+    @Rule
+    @JvmField
+    val logOnExceptionWatcher: TestWatcher =
+        object : TestWatcher() {
+            override fun failed(
+                e: Throwable,
+                description: Description
+            ) {
+                System.err.println(log.toString())
+            }
+        }
+
+    @Test
+    fun testNoChange() {
+        initWithSize(5)
+        check()
+    }
+
+    @Test
+    fun testAddItems() {
+        initWithSize(2)
+        add(1)
+        check()
+    }
+
+    // @Test
+    // @LargeTest
+    // Used for development
+    @Suppress("unused")
+    fun testRandom() {
+        for (x in 0..99) {
+            for (i in 0..99) {
+                for (j in 2..39) {
+                    testRandom(i, j)
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testGen2() {
+        initWithSize(5)
+        add(5)
+        delete(3)
+        delete(1)
+        check()
+    }
+
+    @Test
+    fun testGen3() {
+        initWithSize(5)
+        add(0)
+        delete(1)
+        delete(3)
+        check()
+    }
+
+    @Test
+    fun testGen4() {
+        initWithSize(5)
+        add(5)
+        add(1)
+        add(4)
+        add(4)
+        check()
+    }
+
+    @Test
+    fun testGen5() {
+        initWithSize(5)
+        delete(0)
+        delete(2)
+        add(0)
+        add(2)
+        check()
+    }
+
+    @Test
+    fun testGen6() {
+        initWithSize(2)
+        delete(0)
+        delete(0)
+        check()
+    }
+
+    @Test
+    fun testGen7() {
+        initWithSize(3)
+        move(2, 0)
+        delete(2)
+        add(2)
+        check()
+    }
+
+    @Test
+    fun testGen8() {
+        initWithSize(3)
+        delete(1)
+        add(0)
+        move(2, 0)
+        check()
+    }
+
+    @Test
+    fun testGen9() {
+        initWithSize(2)
+        add(2)
+        move(0, 2)
+        check()
+    }
+
+    @Test
+    fun testGen10() {
+        initWithSize(3)
+        move(0, 1)
+        move(1, 2)
+        add(0)
+        check()
+    }
+
+    @Test
+    fun testGen11() {
+        initWithSize(4)
+        move(2, 0)
+        move(2, 3)
+        check()
+    }
+
+    @Test
+    fun testGen12() {
+        initWithSize(4)
+        move(3, 0)
+        move(2, 1)
+        check()
+    }
+
+    @Test
+    fun testGen13() {
+        initWithSize(4)
+        move(3, 2)
+        move(0, 3)
+        check()
+    }
+
+    @Test
+    fun testGen14() {
+        initWithSize(4)
+        move(3, 2)
+        add(4)
+        move(0, 4)
+        check()
+    }
+
+    @Test
+    fun testAdd1() {
+        initWithSize(1)
+        add(1)
+        check()
+    }
+
+    @Test
+    fun testMove1() {
+        initWithSize(3)
+        move(0, 2)
+        check()
+    }
+
+    @Test
+    fun tmp() {
+        initWithSize(4)
+        move(0, 2)
+        check()
+    }
+
+    @Test
+    fun testUpdate1() {
+        initWithSize(3)
+        update(2)
+        check()
+    }
+
+    @Test
+    fun testUpdate2() {
+        initWithSize(2)
+        add(1)
+        update(1)
+        update(2)
+        check()
+    }
+
+    @Test
+    fun testDisableMoveDetection() {
+        initWithSize(5)
+        move(0, 4)
+        val applied = applyUpdates(
+            before,
+            DiffUtil.calculateDiff(callback, false)
+        )
+        assertThat(
+            applied.size,
+            `is`(5)
+        )
+        assertThat(
+            applied[4].newItem,
+            `is`(true)
+        )
+        assertThat(
+            applied.contains(before[0]),
+            `is`(false)
+        )
+    }
+
+    @Test(expected = IndexOutOfBoundsException::class)
+    fun convertOldPositionToNew_tooSmall() {
+        initWithSize(2)
+        update(2)
+        DiffUtil.calculateDiff(callback).convertOldPositionToNew(-1)
+    }
+
+    @Test(expected = IndexOutOfBoundsException::class)
+    fun convertOldPositionToNew_tooLarge() {
+        initWithSize(2)
+        update(2)
+        DiffUtil.calculateDiff(callback).convertOldPositionToNew(2)
+    }
+
+    @Test(expected = IndexOutOfBoundsException::class)
+    fun convertNewPositionToOld_tooSmall() {
+        initWithSize(2)
+        update(2)
+        DiffUtil.calculateDiff(callback).convertNewPositionToOld(-1)
+    }
+
+    @Test(expected = IndexOutOfBoundsException::class)
+    fun convertNewPositionToOld_tooLarge() {
+        initWithSize(2)
+        update(2)
+        DiffUtil.calculateDiff(callback).convertNewPositionToOld(2)
+    }
+
+    private fun testRandom(initialSize: Int, operationCount: Int) {
+        log.setLength(0)
+        initWithSize(initialSize)
+        for (i in 0 until operationCount) {
+            val op = sRand.nextInt(5)
+            when (op) {
+                0 -> add(sRand.nextInt(after.size + 1))
+                1 -> if (after.isNotEmpty()) {
+                    delete(sRand.nextInt(after.size))
+                }
+                2 -> // move
+                    if (after.size > 0) {
+                        move(
+                            sRand.nextInt(after.size),
+                            sRand.nextInt(after.size)
+                        )
+                    }
+                3 -> // update
+                    if (after.size > 0) {
+                        update(sRand.nextInt(after.size))
+                    }
+                4 -> // update with payload
+                    if (after.size > 0) {
+                        updateWithPayload(sRand.nextInt(after.size))
+                    }
+            }
+        }
+        check()
+    }
+
+    private fun check() {
+        val result =
+            DiffUtil.calculateDiff(callback)
+        log("before", before)
+        log("after", after)
+        log("snakes", result.snakes)
+        // test diff dispatch
+        val applied =
+            applyUpdates(before, result)
+        assertEquals(applied, after)
+        // test position conversion
+        before.indices.forEach { oldPos ->
+            val newPos = result.convertOldPositionToNew(oldPos)
+            if (newPos != DiffUtil.DiffResult.NO_POSITION) {
+                assertEquals(before[oldPos].id, after[newPos].id)
+            } else {
+                assertFalse(after.contains(before[oldPos]))
+            }
+        }
+
+        try {
+            result.convertOldPositionToNew(before.size)
+            Assert.fail("out of bounds should occur")
+        } catch (e: IndexOutOfBoundsException) { // expected
+        }
+        after.indices.forEach { newPos ->
+            val oldPos = result.convertNewPositionToOld(newPos)
+            if (oldPos != DiffUtil.DiffResult.NO_POSITION) {
+                assertEquals(after[newPos].id, before[oldPos].id)
+            } else {
+                assertFalse(before.contains(after[newPos]))
+            }
+        }
+
+        try {
+            result.convertNewPositionToOld(after.size)
+            Assert.fail("out of bounds should occur")
+        } catch (e: IndexOutOfBoundsException) { // expected
+        }
+    }
+
+    private fun initWithSize(size: Int) {
+        before.clear()
+        after.clear()
+        repeat(size) {
+            before.add(Item(false))
+        }
+        after.addAll(before)
+        log.append("initWithSize($size);\n")
+    }
+
+    private fun log(title: String, items: List<*>) {
+        log.append(title).append(":").append(items.size).append("\n")
+        items.forEach { item ->
+            log.append("  ").append(item).append("\n")
+        }
+    }
+
+    private fun assertEquals(
+        applied: List<Item>,
+        after: List<Item>
+    ) {
+        log("applied", applied)
+        val report = log.toString()
+        assertThat(
+            report,
+            applied.size,
+            `is`(after.size)
+        )
+        after.indices.forEach { index ->
+            val item = applied[index]
+            if (after[index].newItem) {
+                assertThat(
+                    report,
+                    item.newItem,
+                    `is`(true)
+                )
+            } else if (after[index].changed) {
+                assertThat(
+                    report,
+                    item.newItem,
+                    `is`(false)
+                )
+                assertThat(
+                    report,
+                    item.changed,
+                    `is`(true)
+                )
+                assertThat(
+                    report,
+                    item.id,
+                    `is`(after[index].id)
+                )
+                assertThat(
+                    report,
+                    item.payload,
+                    `is`(after[index].payload)
+                )
+            } else {
+                assertThat(
+                    report,
+                    item,
+                    equalTo(
+                        after[index]
+                    )
+                )
+            }
+        }
+    }
+
+    private fun applyUpdates(
+        before: List<Item>,
+        result: DiffUtil.DiffResult
+    ): List<Item> {
+        val target = mutableListOf<Item>()
+        target.addAll(before)
+        result.dispatchUpdatesTo(object : ListUpdateCallback {
+            override fun onInserted(position: Int, count: Int) {
+                repeat(count) {
+                    target.add(it + position, Item(true))
+                }
+            }
+
+            override fun onRemoved(position: Int, count: Int) {
+                repeat(count) {
+                    target.removeAt(position)
+                }
+            }
+
+            override fun onMoved(
+                fromPosition: Int,
+                toPosition: Int
+            ) {
+                val item = target.removeAt(fromPosition)
+                target.add(toPosition, item)
+            }
+
+            override fun onChanged(
+                position: Int,
+                count: Int,
+                payload: Any?
+            ) {
+                repeat(count) { offset ->
+                    val positionInList = position + offset
+                    val existing =
+                        target[positionInList]
+                    // make sure we don't update same item twice in callbacks
+                    assertThat(
+                        existing.changed,
+                        `is`(false)
+                    )
+                    assertThat(
+                        existing.newItem,
+                        `is`(false)
+                    )
+                    assertThat(
+                        existing.payload,
+                        `is`(nullValue())
+                    )
+                    val replica = existing.copy(
+                        changed = true
+                    )
+                    target.removeAt(positionInList)
+                    target.add(positionInList, replica)
+                }
+            }
+        })
+        return target
+    }
+
+    private fun add(index: Int) {
+        after.add(index, Item(true))
+        log.append("add(").append(index).append(");\n")
+    }
+
+    private fun delete(index: Int) {
+        after.removeAt(index)
+        log.append("delete(").append(index).append(");\n")
+    }
+
+    private fun update(index: Int) {
+        val existing = after[index]
+        if (existing.newItem) {
+            return // new item cannot be changed
+        }
+        // clean the payload since this might be after an updateWithPayload call
+        val replica = existing.copy(
+            changed = true,
+            payload = null,
+            data = UUID.randomUUID().toString()
+        )
+        after.removeAt(index)
+        after.add(index, replica)
+        log.append("update(").append(index).append(");\n")
+    }
+
+    private fun updateWithPayload(index: Int) {
+        val existing = after[index]
+        if (existing.newItem) {
+            return // new item cannot be changed
+        }
+        val replica = existing.copy(
+            changed = true,
+            data = UUID.randomUUID().toString(),
+            payload = UUID.randomUUID().toString()
+        )
+        after.removeAt(index)
+        after.add(index, replica)
+        log.append("update(").append(index).append(");\n")
+    }
+
+    private fun move(from: Int, to: Int) {
+        val removed = after.removeAt(from)
+        after.add(to, removed)
+        log.append("move(").append(from).append(",").append(to).append(");\n")
+    }
+
+    internal data class Item(
+        val id: Long,
+        val newItem: Boolean,
+        var changed: Boolean = false,
+        var payload: String? = null,
+        var data: String = UUID.randomUUID().toString()
+    ) {
+
+        constructor(newItem: Boolean) : this(id = idCounter++, newItem = newItem)
+
+        companion object {
+            var idCounter: Long = 0
+        }
+    }
+
+    companion object {
+        private val sRand = Random(System.nanoTime())
+    }
+}
\ No newline at end of file
diff --git a/room/common/src/main/java/androidx/room/Query.java b/room/common/src/main/java/androidx/room/Query.java
index 298c7b6..68015fa 100644
--- a/room/common/src/main/java/androidx/room/Query.java
+++ b/room/common/src/main/java/androidx/room/Query.java
@@ -72,7 +72,28 @@
  * UPDATE or DELETE queries can return {@code void} or {@code int}. If it is an {@code int},
  * the value is the number of rows affected by this query.
  * <p>
- * <b>RxJava2</b> If you are using RxJava2, you can also return {@code Flowable<T>} or
+ * <b>Flow</b>
+ * <p>
+ * If you are using Kotlin, you can also return {@code Flow<T>} from query methods. This creates a
+ * {@code Flow<T>} object that emits the results of the query and re-dispatches the query every
+ * time the data in the queried table changes.
+ * <p>
+ * Note that querying a table with a return type of {@code Flow<T>} always returns the first row
+ * in the result set, rather than emitting all of the rows in sequence. To observe changes over
+ * multiple rows in a table, use a return type of {@code Flow<List<T>>} instead.
+ * <p>
+ * Keep nullability in mind when choosing a return type, as it affects how the query method handles
+ * empty tables:
+ * <ul>
+ * <li> <p>When the return type is {@code Flow<T>}, querying an empty table throws a null pointer
+ * exception.
+ * <li> <p>When the return type is {@code Flow<T?>}, querying an empty table emits a null value.
+ * <li> <p>When the return type is {@code Flow<List<T>>}, querying an empty table emits an empty
+ * list. </ul>
+ * <p>
+ * <b>RxJava2</b>
+ * <p>
+ * If you are using RxJava2, you can also return {@code Flowable<T>} or
  * {@code Publisher<T>} from query methods. Since Reactive Streams does not allow {@code null}, if
  * the query returns a nullable type, it will not dispatch anything if the value is {@code null}
  * (like fetching an {@link Entity} row that does not exist).
diff --git a/samples/SupportLeanbackDemos/lint-baseline.xml b/samples/SupportLeanbackDemos/lint-baseline.xml
index d91b2b8..13b4966 100644
--- a/samples/SupportLeanbackDemos/lint-baseline.xml
+++ b/samples/SupportLeanbackDemos/lint-baseline.xml
@@ -31,6 +31,28 @@
     </issue>
 
     <issue
+        id="MissingClass"
+        message="Class referenced in the layout file, `com.example.android.leanback.PlaybackOverlayFragment`, was not found in the project or the libraries"
+        errorLine1="        android:name=&quot;com.example.android.leanback.PlaybackOverlayFragment&quot;"
+        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/layout/playback_controls.xml"
+            line="23"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="MissingClass"
+        message="Class referenced in the layout file, `com.example.android.leanback.PlaybackOverlaySupportFragment`, was not found in the project or the libraries"
+        errorLine1="        android:name=&quot;com.example.android.leanback.PlaybackOverlaySupportFragment&quot;"
+        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/layout/playback_controls_support.xml"
+            line="25"
+            column="23"/>
+    </issue>
+
+    <issue
         id="DefaultLocale"
         message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
         errorLine1="        b.append(String.format(&quot;%.2f&quot;, ((float) seconds + seconds2)));"
@@ -1219,6 +1241,94 @@
     </issue>
 
     <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_SearchDetails` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.SearchDetails&quot; parent=&quot;Theme.AppCompat.Leanback.Details.NoSharedElementTransition&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="23"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_Details` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.Details&quot; parent=&quot;Theme.AppCompat.Leanback.Details&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="25"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_Details_CustomTitle` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.Details.CustomTitle&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="27"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_Rows` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.Rows&quot; parent=&quot;Theme.AppCompat.Leanback&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="32"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.GuidedStep&quot; parent=&quot;Theme.AppCompat.Leanback.GuidedStep&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="36"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep_First` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.GuidedStep.First&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="39"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep_Half` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.GuidedStep.Half&quot; parent=&quot;Theme.AppCompat.Leanback.GuidedStep.Half&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="42"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="UnusedResources"
+        message="The resource `R.style.Theme_Example_AppCompat_Leanback_Preferences` appears to be unused"
+        errorLine1="    &lt;style name=&quot;Theme.Example.AppCompat.Leanback.Preferences&quot;>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/themes_appcompat.xml"
+            line="44"
+            column="12"/>
+    </issue>
+
+    <issue
         id="UselessParent"
         message="This `LinearLayout` layout or its `RelativeLayout` parent is useless"
         errorLine1="    &lt;LinearLayout"
diff --git a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
index 69c295f..18000a4 100644
--- a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
+++ b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
@@ -37,7 +37,7 @@
     companion object {
         private const val DESCRIPTION = "Missing ComponentInitializer no-arg constructor"
         val ISSUE = Issue.create(
-            id = "EnsureComponentInitializerNoArgConstructor",
+            id = "EnsureComponentInitializerNoArgConstr",
             briefDescription = DESCRIPTION,
             explanation = """
                 Every `ComponentInitializer` must have a no argument constructor.
diff --git a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
index 9a0eee4..6eef693 100644
--- a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
+++ b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
@@ -76,7 +76,7 @@
             /* ktlint-disable max-line-length */
             .expect(
                 """
-                src/com/example/TestComponentInitializer.kt:5: Error: Missing ComponentInitializer no-arg constructor [EnsureComponentInitializerNoArgConstructor]
+                src/com/example/TestComponentInitializer.kt:5: Error: Missing ComponentInitializer no-arg constructor [EnsureComponentInitializerNoArgConstr]
                 class TestComponentInitializer(val int: Int): ComponentInitializer<Unit> {
                 ^
                 1 errors, 0 warnings
diff --git a/startup/startup-runtime/build.gradle b/startup/startup-runtime/build.gradle
index 6a4c794..45014d0 100644
--- a/startup/startup-runtime/build.gradle
+++ b/startup/startup-runtime/build.gradle
@@ -39,6 +39,7 @@
 
 dependencies {
     implementation("androidx.annotation:annotation:1.1.0")
+    implementation(project(':tracing:tracing-ktx'))
     lintPublish(project(':startup:startup-runtime-lint'))
     androidTestImplementation(KOTLIN_STDLIB)
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java b/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
index 1d925bd..bda6dcb 100644
--- a/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
+++ b/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 
 import androidx.annotation.NonNull;
+import androidx.tracing.Trace;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -102,11 +103,11 @@
             @NonNull Class<? extends ComponentInitializer<?>> component,
             @NonNull Set<Class<?>> initializing) {
         synchronized (sLock) {
-            boolean isTracingEnabled = TraceCompat.isEnabled();
+            boolean isTracingEnabled = Trace.isEnabled();
             try {
                 if (isTracingEnabled) {
                     // Use the simpleName here because section names would get too big otherwise.
-                    TraceCompat.beginSection(component.getSimpleName());
+                    Trace.beginSection(component.getSimpleName());
                 }
                 if (initializing.contains(component)) {
                     String message = String.format(
@@ -147,7 +148,7 @@
                 }
                 return (T) result;
             } finally {
-                TraceCompat.endSection();
+                Trace.endSection();
             }
         }
     }
@@ -155,7 +156,7 @@
     @SuppressWarnings("unchecked")
     void discoverAndInitialize() {
         try {
-            TraceCompat.beginSection(SECTION_NAME);
+            Trace.beginSection(SECTION_NAME);
             ApplicationInfo applicationInfo =
                     mContext.getPackageManager()
                             .getApplicationInfo(mContext.getPackageName(), GET_META_DATA);
@@ -183,7 +184,7 @@
         } catch (PackageManager.NameNotFoundException | ClassNotFoundException exception) {
             throw new StartupException(exception);
         } finally {
-            TraceCompat.endSection();
+            Trace.endSection();
         }
     }
 }
diff --git a/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java b/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java
deleted file mode 100644
index 16e896b..0000000
--- a/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.startup;
-
-import android.os.Build;
-import android.os.Trace;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-/**
- * Writes trace events to the system trace buffer.  These trace events can be
- * collected and visualized using the Systrace tool.
- *
- * <p>This tracing mechanism is independent of the method tracing mechanism
- * offered by {@link android.os.Debug#startMethodTracing}.  In particular, it enables
- * tracing of events that occur across multiple processes.
- * <p>For information about using the Systrace tool, read <a
- * href="{@docRoot}studio/profile/systrace/">Overview of system tracing</a>.
- */
-final class TraceCompat {
-
-    private static final String TAG = "TraceCompat";
-
-    private static long sTraceTagApp;
-    private static Method sIsTagEnabledMethod;
-
-    static {
-        if (Build.VERSION.SDK_INT >= 18 && Build.VERSION.SDK_INT < 29) {
-            try {
-                Field traceTagAppField = Trace.class.getField("TRACE_TAG_APP");
-                sTraceTagApp = traceTagAppField.getLong(null);
-                sIsTagEnabledMethod = Trace.class.getMethod("isTagEnabled", long.class);
-            } catch (Exception e) {
-                Log.i(TAG, "Unable to initialize via reflection.", e);
-            }
-        }
-    }
-
-    /**
-     * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate
-     * string creation for trace sections that require formatting. It is not necessary
-     * to guard all Trace method calls as they internally already check this. However it is
-     * recommended to use this to prevent creating any temporary objects that would then be
-     * passed to those methods to reduce runtime cost when tracing isn't enabled.
-     *
-     * @return true if tracing is currently enabled, false otherwise
-     */
-    public static boolean isEnabled() {
-        if (Build.VERSION.SDK_INT >= 29) {
-            return Trace.isEnabled();
-        } else if (Build.VERSION.SDK_INT >= 18) {
-            try {
-                return (boolean) sIsTagEnabledMethod.invoke(null, sTraceTagApp);
-            } catch (Exception e) {
-                Log.v(TAG, "Unable to invoke isTagEnabled() via reflection.");
-            }
-        }
-
-        // Never enabled on < API 18
-        return false;
-    }
-
-    /**
-     * Writes a trace message to indicate that a given section of code has begun. This call must
-     * be followed by a corresponding call to {@link #endSection()} on the same thread.
-     *
-     * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
-     * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
-     * these characters they will be replaced with a space character in the trace.
-     *
-     * @param sectionName The name of the code section to appear in the trace.  This may be at
-     * most 127 Unicode code units long.
-     */
-    public static void beginSection(@NonNull String sectionName) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            Trace.beginSection(sectionName);
-        }
-    }
-
-    /**
-     * Writes a trace message to indicate that a given section of code has ended. This call must
-     * be preceded by a corresponding call to {@link #beginSection(String)}. Calling this method
-     * will mark the end of the most recently begun section of code, so care must be taken to
-     * ensure that beginSection / endSection pairs are properly nested and called from the same
-     * thread.
-     */
-    public static void endSection() {
-        if (Build.VERSION.SDK_INT >= 18) {
-            Trace.endSection();
-        }
-    }
-
-    private TraceCompat() {}
-}
diff --git a/tracing/tracing-ktx/src/main/AndroidManifest.xml b/tracing/tracing-ktx/src/main/AndroidManifest.xml
index 976de72..ede3fba 100644
--- a/tracing/tracing-ktx/src/main/AndroidManifest.xml
+++ b/tracing/tracing-ktx/src/main/AndroidManifest.xml
@@ -15,6 +15,6 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="androidx.tracing">
+    package="androidx.tracing.ktx">
 
 </manifest>
diff --git a/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java b/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
index cbe3564..40ac8f1 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
+++ b/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
@@ -287,10 +287,20 @@
                 float offsetLargerThanSize = SIZE * 2;
                 Matrix matrix = new Matrix();
                 matrix.postTranslate(0f, offsetLargerThanSize);
-                Matrix invertedMatrix = new Matrix();
-                invertedMatrix.postTranslate(0f, -offsetLargerThanSize);
                 GhostViewUtils.addGhost(view, parent2, matrix);
-                ViewUtils.setAnimationMatrix(view, invertedMatrix);
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
+                        && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+                    // this test uses setAnimationMatrix which applies the matrix for the
+                    // RenderNode starting from 21 and RenderNode is only used with the
+                    // hardware acceleration. and the logic we use in drawBitmap() is drawing
+                    // without the hardware acceleration for the API before 26. so instead of
+                    // setAnimationMatrix we will just use TranslationY for this API versions
+                    view.setTranslationY(-offsetLargerThanSize);
+                } else {
+                    Matrix invertedMatrix = new Matrix();
+                    invertedMatrix.postTranslate(0f, -offsetLargerThanSize);
+                    ViewUtils.setAnimationMatrix(view, invertedMatrix);
+                }
             }
         });
 
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
index 7c87816..d91145b 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
@@ -41,7 +41,7 @@
                 mass = 491.0,
                 springConstant = 4500.0,
                 dampingCoefficient = dampingCoeff,
-                initialPosition = -3000.0,
+                initialDisplacement = -3000.0,
                 initialVelocity = 800.0,
                 delta = 1.0
             )
@@ -56,7 +56,7 @@
                 mass = 81.0,
                 springConstant = 130321.0,
                 dampingCoefficient = 6501.0,
-                initialPosition = -200000.0,
+                initialDisplacement = -200000.0,
                 initialVelocity = 4200.0,
                 delta = 1.0
             )
@@ -71,7 +71,7 @@
                 mass = 1.0,
                 springConstant = 1.0,
                 dampingCoefficient = 1.0,
-                initialPosition = -200000.0,
+                initialDisplacement = -200000.0,
                 initialVelocity = 100.0,
                 delta = 1.0
             )
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
index 3f2a74f..f1845a6 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
@@ -22,10 +22,10 @@
 import androidx.test.filters.LargeTest
 import androidx.ui.benchmark.ComposeBenchmarkRule
 import androidx.ui.benchmark.toggleStateBenchmarkLayout
+import androidx.ui.integration.test.ToggleableTestCase
 import androidx.ui.layout.Center
 import androidx.ui.layout.Container
 import androidx.ui.test.ComposeTestCase
-import androidx.ui.integration.test.ToggleableTestCase
 import androidx.ui.unit.Dp
 import androidx.ui.unit.dp
 import org.junit.Rule
@@ -67,11 +67,14 @@
     @Composable
     private fun StaticChildren(count: Int) {
         if (count > 0) {
-            Container(width = 100.dp, height = 100.dp) {
+            val modifier = if (count == 1) {
+                onPositioned { it.size }
+            } else {
+                Modifier.None
+            }
+            Container(modifier, width = 100.dp, height = 100.dp) {
                 StaticChildren(count - 1)
             }
-        } else {
-            OnPositioned { coordinates -> coordinates.size }
         }
     }
 
diff --git a/ui/settings.gradle b/ui/settings.gradle
index fc7f4a4..f25e347 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -43,6 +43,8 @@
 includeProject(":compose:compose-runtime-benchmark", "../compose/compose-runtime/compose-runtime-benchmark")
 includeProject(":compose:compose-runtime:samples", "../compose/compose-runtime/samples")
 includeProject(":lint-checks", "../lint-checks")
+includeProject(":tracing:tracing", "../tracing/tracing")
+includeProject(":tracing:tracing-ktx", "../tracing/tracing-ktx")
 includeProject(":ui:integration-tests:benchmark", "integration-tests/benchmark")
 includeProject(":ui:integration-tests:demos", "integration-tests/demos")
 includeProject(":ui:integration-tests:test", "integration-tests/test")
@@ -88,6 +90,7 @@
 includeProject(":ui:ui-unit:samples", "ui-unit/samples")
 includeProject(":ui:ui-util", "ui-util")
 includeProject(":ui:ui-vector", "ui-vector")
+includeProject(":ui:ui-saved-instance-state", "ui-saved-instance-state")
 
 /////////////////////////////
 //
diff --git a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
index 0009f95..c601921 100644
--- a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
+++ b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
@@ -54,6 +54,7 @@
 import androidx.text.LayoutCompat.TextLayoutAlignment
 import androidx.text.style.BaselineShiftSpan
 import kotlin.math.ceil
+import kotlin.math.min
 
 /**
  * Wrapper for Static Text Layout classes.
@@ -122,6 +123,8 @@
     @VisibleForTesting
     val layout: Layout
 
+    val lineCount: Int
+
     init {
         val end = charSequence.length
         val frameworkTextDir = getTextDirectionHeuristic(textDirectionHeuristic)
@@ -188,16 +191,18 @@
         } else {
             layout.lineCount > maxLines
         }
+        lineCount = min(layout.lineCount, maxLines)
     }
 
-    val lineCount: Int
-        get() = layout.lineCount
-
     val text: CharSequence
         get() = layout.text
 
     val height: Int
-        get() = layout.height
+        get() = if (didExceedMaxLines) {
+            layout.getLineBottom(lineCount - 1)
+        } else {
+            layout.height
+        }
 
     fun getLineLeft(lineIndex: Int): Float = layout.getLineLeft(lineIndex)
 
diff --git a/ui/ui-animation-core/api/0.1.0-dev07.txt b/ui/ui-animation-core/api/0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/0.1.0-dev07.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/api/current.txt b/ui/ui-animation-core/api/current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/current.txt
+++ b/ui/ui-animation-core/api/current.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/api/public_plus_experimental_current.txt b/ui/ui-animation-core/api/public_plus_experimental_current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_current.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt b/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/api/restricted_current.txt b/ui/ui-animation-core/api/restricted_current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/restricted_current.txt
+++ b/ui/ui-animation-core/api/restricted_current.txt
@@ -157,10 +157,10 @@
 
   public interface DecayAnimation {
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public abstract float absVelocityThreshold;
   }
 
@@ -194,10 +194,10 @@
     ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
   }
 
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt b/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
index 403877f..6626e48 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
@@ -232,15 +232,6 @@
     private lateinit var valueVector: V
     private lateinit var velocityVector: V
 
-    override fun isFinished(playTime: Long, start: V, end: V, startVelocity: V): Boolean {
-        for (i in 0 until start.size) {
-            if (!anim.isFinished(playTime, start[i], end[i], startVelocity[i])) {
-                return false
-            }
-        }
-        return true
-    }
-
     override fun getValue(playTime: Long, start: V, end: V, startVelocity: V): V {
         if (!::valueVector.isInitialized) {
             valueVector = start.newInstance()
@@ -253,13 +244,24 @@
 
     override fun getVelocity(playTime: Long, start: V, end: V, startVelocity: V): V {
         if (!::velocityVector.isInitialized) {
-            velocityVector = start.newInstance()
+            velocityVector = startVelocity.newInstance()
         }
         for (i in 0 until velocityVector.size) {
             velocityVector[i] = anim.getVelocity(playTime, start[i], end[i], startVelocity[i])
         }
         return velocityVector
     }
+
+    override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+        var maxDuration = 0L
+        (0 until start.size).forEach {
+            maxDuration = maxOf(
+                maxDuration,
+                anim.getDurationMillis(start[it], end[it], startVelocity[it])
+            )
+        }
+        return maxDuration
+    }
 }
 
 /**
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
index 0dcdb8e..9152843 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
@@ -37,19 +37,6 @@
     val absVelocityThreshold: Float
 
     /**
-     * Returns whether the animation is finished at the given time.
-     *
-     * @param playTime The time elapsed in milliseconds since the start of the animation
-     * @param start The start value of the animation
-     * @param startVelocity The start velocity of the animation
-     */
-    fun isFinished(
-        playTime: Long,
-        start: Float,
-        startVelocity: Float
-    ): Boolean
-
-    /**
      * Returns the value of the animation at the given time.
      *
      * @param playTime The time elapsed in milliseconds since the start of the animation
@@ -62,6 +49,11 @@
         startVelocity: Float
     ): Float
 
+    fun getDurationMillis(
+        start: Float,
+        startVelocity: Float
+    ): Long
+
     /**
      * Returns the velocity of the animation at the given time.
      *
@@ -105,14 +97,6 @@
     override val absVelocityThreshold: Float = max(0.0000001f, abs(absVelocityThreshold))
     private val friction: Float = ExponentialDecayFriction * max(0.0001f, frictionMultiplier)
 
-    override fun isFinished(
-        playTime: Long,
-        start: Float,
-        startVelocity: Float
-    ): Boolean {
-        return abs(getVelocity(playTime, start, startVelocity)) <= absVelocityThreshold
-    }
-
     override fun getValue(
         playTime: Long,
         start: Float,
@@ -130,6 +114,11 @@
         return (startVelocity * exp(((playTime / 1000f) * friction)))
     }
 
+    override fun getDurationMillis(start: Float, startVelocity: Float): Long {
+        // Inverse of getVelocity
+        return (1000f * ln(absVelocityThreshold / abs(startVelocity)) / friction).toLong()
+    }
+
     override fun getTarget(
         start: Float,
         startVelocity: Float
@@ -164,6 +153,7 @@
             return target
         }
     }
+
     override fun getVelocity(playTime: Long): AnimationVector1D {
         if (!isFinished(playTime)) {
             velocityVector.value = anim.getVelocity(playTime, startValue, startVelocity)
@@ -172,8 +162,8 @@
         }
         return velocityVector
     }
-    override fun isFinished(playTime: Long): Boolean =
-        anim.isFinished(playTime, startValue, startVelocity)
+
+    override val durationMillis: Long = anim.getDurationMillis(startValue, startVelocity)
 }
 
 internal fun DecayAnimation.createWrapper(
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
index 8895469..723a2cb 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
@@ -20,13 +20,6 @@
  * FloatAnimation interface to avoid boxing/unboxing on floats.
  */
 internal interface FloatAnimation {
-    fun isFinished(
-        playTime: Long,
-        start: Float,
-        end: Float,
-        startVelocity: Float
-    ): Boolean
-
     fun getValue(
         playTime: Long,
         start: Float,
@@ -40,6 +33,16 @@
         end: Float,
         startVelocity: Float
     ): Float
+
+    /**
+     * Note that this may be a computation that is expensive - especially with spring based
+     * animations
+     */
+    fun getDurationMillis(
+        start: Float,
+        end: Float,
+        startVelocity: Float
+    ): Long
 }
 
 /**
@@ -111,16 +114,6 @@
         it.stiffness = stiffness
     }
 
-    override fun isFinished(
-        playTime: Long,
-        start: Float,
-        end: Float,
-        startVelocity: Float
-    ): Boolean {
-        spring.finalPosition = end
-        return spring.isAtEquilibrium(start, startVelocity, playTime)
-    }
-
     override fun getValue(
         playTime: Long,
         start: Float,
@@ -142,6 +135,15 @@
         val (_, velocity) = spring.updateValues(start, startVelocity, playTime)
         return velocity
     }
+
+    override fun getDurationMillis(start: Float, end: Float, startVelocity: Float): Long =
+        estimateAnimationDurationMillis(
+            stiffness = spring.stiffness,
+            dampingRatio = spring.dampingRatio,
+            initialDisplacement = (start - end) * 100f,
+            initialVelocity = startVelocity * 100f,
+            delta = 1f
+        )
 }
 
 /**
@@ -154,13 +156,6 @@
     val delay: Long,
     private val easing: Easing
 ) : FloatAnimation {
-    override fun isFinished(
-        playTime: Long,
-        start: Float,
-        end: Float,
-        startVelocity: Float
-    ): Boolean = playTime >= delay + duration
-
     override fun getValue(
         playTime: Long,
         start: Float,
@@ -177,6 +172,10 @@
         return (playTime - delay).coerceIn(0, duration)
     }
 
+    override fun getDurationMillis(start: Float, end: Float, startVelocity: Float): Long {
+        return delay + duration
+    }
+
     /**
      * Calculate velocity by difference between the current value and the value 1 ms ago. This is a
      * preliminary way of calculating velocity used by easing curve based animations, and keyframe
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
index bf32420..2126129 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
@@ -28,10 +28,28 @@
  */
 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
 fun estimateAnimationDurationMillis(
+    stiffness: Float,
+    dampingRatio: Float,
+    initialVelocity: Float,
+    initialDisplacement: Float,
+    delta: Float
+): Long = estimateAnimationDurationMillis(
+    stiffness = stiffness.toDouble(),
+    dampingRatio = dampingRatio.toDouble(),
+    initialVelocity = initialVelocity.toDouble(),
+    initialDisplacement = initialDisplacement.toDouble(),
+    delta = delta.toDouble()
+)
+
+/**
+ * Returns the estimated time that the spring will last be at [delta]
+ */
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+fun estimateAnimationDurationMillis(
     stiffness: Double,
     dampingRatio: Double,
     initialVelocity: Double,
-    initialPosition: Double,
+    initialDisplacement: Double,
     delta: Double
 ): Long {
     val dampingCoefficient = 2.0 * dampingRatio * sqrt(stiffness)
@@ -41,7 +59,7 @@
         roots,
         dampingRatio,
         initialVelocity,
-        initialPosition,
+        initialDisplacement,
         delta
     )
 }
@@ -55,14 +73,20 @@
     dampingCoefficient: Double,
     mass: Double,
     initialVelocity: Double,
-    initialPosition: Double,
+    initialDisplacement: Double,
     delta: Double
 ): Long {
     val criticalDamping = 2.0 * sqrt(springConstant * mass)
     val dampingRatio = dampingCoefficient / criticalDamping
     val roots = complexQuadraticFormula(mass, dampingCoefficient, springConstant)
 
-    return estimateDurationInternal(roots, dampingRatio, initialVelocity, initialPosition, delta)
+    return estimateDurationInternal(
+        roots = roots,
+        dampingRatio = dampingRatio,
+        initialVelocity = initialVelocity,
+        initialPosition = initialDisplacement,
+        delta = delta
+    )
 }
 
 /**
@@ -285,4 +309,5 @@
     return x - fn(x) / fnPrime(x)
 }
 
-private fun Double.isNotFinite() = !this.isFinite()
+@Suppress("NOTHING_TO_INLINE")
+private inline fun Double.isNotFinite() = !this.isFinite()
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
index 3c83b39..99b0935 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
@@ -33,13 +33,6 @@
  */
 // TODO: Use Duration or TimeStamp for playtime once they are inlined.
 internal interface Animation<V : AnimationVector> {
-    fun isFinished(
-        playTime: Long,
-        start: V,
-        end: V,
-        startVelocity: V
-    ): Boolean
-
     fun getValue(
         playTime: Long,
         start: V,
@@ -53,6 +46,12 @@
         end: V,
         startVelocity: V
     ): V
+
+    fun getDurationMillis(
+        start: V,
+        end: V,
+        startVelocity: V
+    ): Long
 }
 
 /**
@@ -69,12 +68,7 @@
      */
     val delay: Long
 
-    override fun isFinished(
-        playTime: Long,
-        start: V,
-        end: V,
-        startVelocity: V
-    ): Boolean = playTime >= delay + duration
+    override fun getDurationMillis(start: V, end: V, startVelocity: V): Long = delay + duration
 
     fun clampPlayTime(playTime: Long): Long {
         return (playTime - delay).coerceIn(0, duration)
@@ -171,9 +165,6 @@
  * [SnapAnimation] immediately snaps the animating value to the end value.
  */
 internal class SnapAnimation<V : AnimationVector> : Animation<V> {
-    override fun isFinished(playTime: Long, start: V, end: V, startVelocity: V): Boolean {
-        return true
-    }
 
     override fun getValue(playTime: Long, start: V, end: V, startVelocity: V): V {
         return end
@@ -182,6 +173,10 @@
     override fun getVelocity(playTime: Long, start: V, end: V, startVelocity: V): V {
         return startVelocity
     }
+
+    override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+        return 0
+    }
 }
 
 /**
@@ -217,14 +212,6 @@
         } else
             startVelocity
 
-    override fun isFinished(
-        playTime: Long,
-        start: V,
-        end: V,
-        startVelocity: V
-    ): Boolean =
-        duration <= 0 || playTime / duration >= iterationCount
-
     override fun getValue(
         playTime: Long,
         start: V,
@@ -252,6 +239,10 @@
             repetitionStartVelocity(playTime, start, startVelocity, end)
         )
     }
+
+    override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+        return iterationCount * duration
+    }
 }
 
 internal class Animation1D(
@@ -259,13 +250,6 @@
 ) : Animation<AnimationVector1D> {
     private val tempVelocityVector = AnimationVector1D(0f)
     private val tempValueVector = AnimationVector1D(0f)
-    override fun isFinished(
-        playTime: Long,
-        start: AnimationVector1D,
-        end: AnimationVector1D,
-        startVelocity: AnimationVector1D
-    ): Boolean =
-        anim.isFinished(playTime, start.value, end.value, startVelocity.value)
 
     override fun getValue(
         playTime: Long,
@@ -286,6 +270,14 @@
         tempVelocityVector.apply {
             value = anim.getVelocity(playTime, start.value, end.value, startVelocity.value)
         }
+
+    override fun getDurationMillis(
+        start: AnimationVector1D,
+        end: AnimationVector1D,
+        startVelocity: AnimationVector1D
+    ): Long {
+        return anim.getDurationMillis(start.value, end.value, startVelocity.value)
+    }
 }
 
 /**
@@ -297,15 +289,6 @@
 ) : Animation<AnimationVector2D> {
     private var velocityVector: AnimationVector2D = AnimationVector2D(0f, 0f)
     private var valueVector: AnimationVector2D = AnimationVector2D(0f, 0f)
-    override fun isFinished(
-        playTime: Long,
-        start: AnimationVector2D,
-        end: AnimationVector2D,
-        startVelocity: AnimationVector2D
-    ): Boolean {
-        return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
-                a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2)
-    }
 
     override fun getValue(
         playTime: Long,
@@ -328,6 +311,17 @@
         velocityVector.v2 = a2.getVelocity(playTime, start.v2, end.v2, startVelocity.v2)
         return velocityVector
     }
+
+    override fun getDurationMillis(
+        start: AnimationVector2D,
+        end: AnimationVector2D,
+        startVelocity: AnimationVector2D
+    ): Long {
+        return maxOf(
+            a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+            a2.getDurationMillis(start.v2, end.v2, startVelocity.v2)
+        )
+    }
 }
 
 /**
@@ -340,16 +334,6 @@
 ) : Animation<AnimationVector3D> {
     private var velocityVector: AnimationVector3D = AnimationVector3D(0f, 0f, 0f)
     private var valueVector: AnimationVector3D = AnimationVector3D(0f, 0f, 0f)
-    override fun isFinished(
-        playTime: Long,
-        start: AnimationVector3D,
-        end: AnimationVector3D,
-        startVelocity: AnimationVector3D
-    ): Boolean {
-        return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
-                a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2) &&
-                a3.isFinished(playTime, start.v3, end.v3, startVelocity.v3)
-    }
 
     override fun getValue(
         playTime: Long,
@@ -374,6 +358,18 @@
         velocityVector.v3 = a3.getVelocity(playTime, start.v3, end.v3, startVelocity.v3)
         return velocityVector
     }
+
+    override fun getDurationMillis(
+        start: AnimationVector3D,
+        end: AnimationVector3D,
+        startVelocity: AnimationVector3D
+    ): Long {
+        return maxOf(
+            a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+            a2.getDurationMillis(start.v2, end.v2, startVelocity.v2),
+            a3.getDurationMillis(start.v3, end.v3, startVelocity.v3)
+        )
+    }
 }
 
 /**
@@ -387,17 +383,6 @@
 ) : Animation<AnimationVector4D> {
     private var velocityVector: AnimationVector4D = AnimationVector4D(0f, 0f, 0f, 0f)
     private var valueVector: AnimationVector4D = AnimationVector4D(0f, 0f, 0f, 0f)
-    override fun isFinished(
-        playTime: Long,
-        start: AnimationVector4D,
-        end: AnimationVector4D,
-        startVelocity: AnimationVector4D
-    ): Boolean {
-        return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
-                a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2) &&
-                a3.isFinished(playTime, start.v3, end.v3, startVelocity.v3) &&
-                a4.isFinished(playTime, start.v4, end.v4, startVelocity.v4)
-    }
 
     override fun getValue(
         playTime: Long,
@@ -424,6 +409,21 @@
         velocityVector.v4 = a4.getVelocity(playTime, start.v4, end.v4, startVelocity.v4)
         return velocityVector
     }
+
+    override fun getDurationMillis(
+        start: AnimationVector4D,
+        end: AnimationVector4D,
+        startVelocity: AnimationVector4D
+    ): Long {
+        return maxOf(
+            a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+            a2.getDurationMillis(start.v2, end.v2, startVelocity.v2),
+            maxOf(
+                a3.getDurationMillis(start.v3, end.v3, startVelocity.v3),
+                a4.getDurationMillis(start.v4, end.v4, startVelocity.v4)
+            )
+        )
+    }
 }
 
 /**
@@ -435,7 +435,10 @@
 internal interface AnimationWrapper<T, V : AnimationVector> {
     fun getValue(playTime: Long): T
     fun getVelocity(playTime: Long): V
-    fun isFinished(playTime: Long): Boolean
+    fun isFinished(playTime: Long): Boolean {
+        return playTime >= durationMillis
+    }
+    val durationMillis: Long
 }
 
 /**
@@ -454,8 +457,6 @@
 ) : AnimationWrapper<T, V> {
     private val startValueVector = typeConverter.convertToVector.invoke(startValue)
     private val endValueVector = typeConverter.convertToVector.invoke(endValue)
-    override fun isFinished(playTime: Long) =
-        animation.isFinished(playTime, startValueVector, endValueVector, startVelocity)
 
     override fun getValue(playTime: Long): T =
         typeConverter.convertFromVector.invoke(
@@ -465,6 +466,12 @@
             )
         )
 
+    override val durationMillis: Long = animation.getDurationMillis(
+        start = startValueVector,
+        end = endValueVector,
+        startVelocity = startVelocity
+    )
+
     override fun getVelocity(playTime: Long): V =
         animation.getVelocity(playTime, startValueVector, endValueVector, startVelocity)
 }
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt b/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
index 4ac6ab6..e341412 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
@@ -24,9 +24,6 @@
         AnimationVector1D(0f)
     ).value
 
-internal fun Animation<AnimationVector1D>.isFinished(time: Int): Boolean =
-    isFinished(time.toLong(), AnimationVector1D(0f), AnimationVector1D(1f), AnimationVector1D(0f))
-
 // Convenient method to build a Float animation.
 internal fun AnimationBuilder<Float>.build() = this.build(FloatToVectorConverter)
 
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
index 7e831a2..8a39417 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
@@ -36,11 +36,12 @@
         val animWrapper = anim.createWrapper(startValue, startVelocity)
         // Obtain finish value by passing in an absurdly large playtime.
         val finishValue = animWrapper.getValue(Int.MAX_VALUE.toLong())
+        val finishTime = animWrapper.durationMillis
 
         for (playTime in 0L..4000L step 200L) {
             val value = anim.getValue(playTime, startValue, startVelocity)
             val velocity = anim.getVelocity(playTime, startValue, startVelocity)
-            val finished = anim.isFinished(playTime, startValue, startVelocity)
+            val finished = playTime >= finishTime
             assertTrue(finished == animWrapper.isFinished(playTime))
 
             if (!finished) {
@@ -48,12 +49,15 @@
                 assertTrue(Math.abs(velocity) >= 2.0f)
                 assertEquals(value, animWrapper.getValue(playTime), epsilon)
                 assertEquals(velocity, animWrapper.getVelocity(playTime).value, epsilon)
+                assertTrue(playTime < finishTime)
             } else {
                 // When the animation is finished, expect absolute velocity < threshold
                 assertTrue(Math.abs(velocity) < 2.0f)
 
                 // Once the animation is finished, the value should not change any more
                 assertEquals(finishValue, animWrapper.getValue(playTime), epsilon)
+
+                assertTrue(playTime >= finishTime)
             }
         }
     }
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
index 38a57d4..c6a262b 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
@@ -17,6 +17,7 @@
 package androidx.animation
 
 import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -88,6 +89,108 @@
         assertThat(resultVelocity).isEqualTo(expectedVelocity)
     }
 
+    @Test
+    fun testCriticallydampedDuration() {
+        val startValue = 100f
+        val endValue = 0f
+        val startVelocity = 3000f
+        val stiffness = 100f
+        val delta = 1.0
+
+        val criticalBuilder = PhysicsBuilder<Float>(
+            dampingRatio = 1f,
+            stiffness = stiffness
+        )
+        val criticalWrapper = criticalBuilder.build().toWrapper(
+            startValue = startValue,
+            endValue = endValue,
+            startVelocity = startVelocity
+        )
+
+        assertEquals(
+            estimateAnimationDurationMillis(
+                stiffness = stiffness.toDouble(),
+                dampingRatio = 1.0,
+                initialVelocity = startVelocity.toDouble() * 100.0,
+                initialDisplacement = startValue.toDouble() * 100.0,
+                delta = delta
+            ) /* = 811 ms*/,
+            criticalWrapper.durationMillis
+        )
+    }
+
+    @Test
+    fun testOverdampedDuration() {
+        val startValue = 100f
+        val endValue = 0f
+        val startVelocity = 3000f
+        val stiffness = 100f
+        val delta = 1.0
+
+        val overBuilder = PhysicsBuilder<Float>(
+            dampingRatio = 5f,
+            stiffness = stiffness
+        )
+        val overWrapper = overBuilder.build().toWrapper(
+            startValue = startValue,
+            endValue = endValue,
+            startVelocity = startVelocity
+        )
+
+        assertEquals(
+            estimateAnimationDurationMillis(
+                stiffness = stiffness.toDouble(),
+                dampingRatio = 5.0,
+                initialVelocity = startVelocity.toDouble() * 100.0,
+                initialDisplacement = startValue.toDouble() * 100.0,
+                delta = delta
+            ) /* = 4830 ms*/,
+            overWrapper.durationMillis
+        )
+    }
+    @Test
+    fun testUnderdampedDuration() {
+        val startValue = 100f
+        val endValue = 0f
+        val startVelocity = 3000f
+        val stiffness = 100f
+        val delta = 1.0
+
+        val underBuilder = PhysicsBuilder<Float>(
+            dampingRatio = .5f,
+            stiffness = stiffness
+        )
+        val underWrapper = underBuilder.build().toWrapper(
+            startValue = startValue,
+            endValue = endValue,
+            startVelocity = startVelocity
+        )
+
+        assertEquals(
+            estimateAnimationDurationMillis(
+                stiffness = stiffness.toDouble(),
+                dampingRatio = 0.5,
+                initialVelocity = startVelocity.toDouble() * 100.0,
+                initialDisplacement = startValue.toDouble() * 100.0,
+                delta = delta) /* = 1206 ms*/,
+            underWrapper.durationMillis
+        )
+    }
+
+    private fun Animation<AnimationVector1D>.toWrapper(
+        startValue: Float,
+        startVelocity: Float,
+        endValue: Float
+    ): AnimationWrapper<Float, AnimationVector1D> {
+        return TargetBasedAnimationWrapper(
+            startValue = startValue,
+            startVelocity = AnimationVector(startVelocity),
+            endValue = endValue,
+            animation = this,
+            typeConverter = FloatToVectorConverter
+        )
+    }
+
     private fun PhysicsBuilder<out Number>.toSpring(endValue: Number) =
         SpringSimulation(endValue.toFloat()).also {
             it.dampingRatio = dampingRatio
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
index f46c8d6..192ba6f 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
@@ -17,6 +17,7 @@
 package androidx.animation
 
 import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -24,12 +25,15 @@
 @RunWith(JUnit4::class)
 class RepeatableAnimationTest {
 
-    private val Duration = 50
-
     private val Animation = TweenBuilder<Float>().apply {
         duration = Duration
     }
 
+    private val DelayedAnimation = TweenBuilder<Float>().apply {
+        delay = DelayDuration
+        duration = Duration
+    }
+
     @Test
     fun twoRepeatsValuesCalculation() {
         val repeat = RepeatableBuilder<Float>().run {
@@ -37,13 +41,42 @@
             animation = Animation
             build()
         }
+        val animationWrapper = TargetBasedAnimationWrapper(
+            0f,
+            AnimationVector(0f),
+            0f,
+            repeat,
+            FloatToVectorConverter
+        )
 
         assertThat(repeat.at(0)).isEqualTo(0f)
         assertThat(repeat.at(Duration - 1)).isGreaterThan(0.9f)
         assertThat(repeat.at(Duration + 1)).isLessThan(0.1f)
         assertThat(repeat.at(Duration * 2 - 1)).isGreaterThan(0.9f)
         assertThat(repeat.at(Duration * 2)).isEqualTo(1f)
-        assertThat(repeat.isFinished(Duration * 2 - 1)).isFalse()
-        assertThat(repeat.isFinished(Duration * 2)).isTrue()
+        assertThat(animationWrapper.isFinished(Duration * 2L - 1L)).isFalse()
+        assertThat(animationWrapper.isFinished(Duration * 2L)).isTrue()
+    }
+
+    @Test
+    fun testRepeatedAnimationDuration() {
+        val iters = 5
+        val repeat = RepeatableBuilder<Float>().apply {
+            iterations = iters
+            animation = DelayedAnimation
+        }.build()
+
+        val duration = repeat.getDurationMillis(
+            AnimationVector1D(0f),
+            AnimationVector1D(0f),
+            AnimationVector1D(0f)
+        )
+
+        assertEquals((DelayDuration + Duration) * iters.toLong(), duration)
+    }
+
+    private companion object {
+        private val DelayDuration = 13
+        private val Duration = 50
     }
 }
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
index 2db045e..1475fa9 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
@@ -27,8 +27,15 @@
     @Test
     fun isFinishedAtTheBeginning() {
         val animation = SnapBuilder<Float>().build()
+        val animationWrapper = TargetBasedAnimationWrapper(
+            0f,
+            AnimationVector(0f),
+            0f,
+            animation,
+            FloatToVectorConverter
+        )
 
         assertThat(animation.at(0)).isEqualTo(1f)
-        assertThat(animation.isFinished(0)).isTrue()
+        assertThat(animationWrapper.isFinished(0)).isTrue()
     }
 }
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
index 45c96d3b..c14bc41 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
@@ -84,7 +84,7 @@
             mass = testCase.mass,
             springConstant = testCase.springConstant,
             dampingCoefficient = testCase.dampingCoefficient,
-            initialPosition = testCase.initialPosition,
+            initialDisplacement = testCase.initialDisplacement,
             initialVelocity = testCase.initialVelocity,
             delta = 1.0
         )
@@ -92,7 +92,7 @@
         val alternateEndTime = estimateAnimationDurationMillis(
             stiffness = testCase.stiffness,
             dampingRatio = testCase.dampingRatio,
-            initialPosition = testCase.initialPosition,
+            initialDisplacement = testCase.initialDisplacement,
             initialVelocity = testCase.initialVelocity,
             delta = 1.0
         )
@@ -110,17 +110,17 @@
             return TestCaseResult(false, testCase, "End time +infinity")
 
         val simTwoFramesAfter = springSimulation.updateValues(
-            lastDisplacement = testCase.initialPosition.toFloat(),
+            lastDisplacement = testCase.initialDisplacement.toFloat(),
             lastVelocity = testCase.initialVelocity.toFloat(),
             timeElapsed = endTime + TwoFrames60fpsMillis
         )
         val simTwoFramesBefore = springSimulation.updateValues(
-            lastDisplacement = testCase.initialPosition.toFloat(),
+            lastDisplacement = testCase.initialDisplacement.toFloat(),
             lastVelocity = testCase.initialVelocity.toFloat(),
             timeElapsed = max(endTime - TwoFrames60fpsMillis, 0L)
         )
         val simAtTime = springSimulation.updateValues(
-            lastDisplacement = testCase.initialPosition.toFloat(),
+            lastDisplacement = testCase.initialDisplacement.toFloat(),
             lastVelocity = testCase.initialVelocity.toFloat(),
             timeElapsed = endTime
         )
@@ -164,7 +164,7 @@
                             springConstant = k,
                             dampingCoefficient = c.toDouble(),
                             initialVelocity = v0.toDouble(),
-                            initialPosition = p0.toDouble()
+                            initialDisplacement = p0.toDouble()
                         )
                         synchronized(testCases) {
                             testCases.add(
@@ -189,7 +189,7 @@
                         springConstant = k,
                         dampingCoefficient = c,
                         initialVelocity = v0.toDouble(),
-                        initialPosition = p0.toDouble()
+                        initialDisplacement = p0.toDouble()
                     )
 
                     synchronized(testCases) {
@@ -208,7 +208,7 @@
         val springConstant: Double,
         val dampingCoefficient: Double,
         val initialVelocity: Double,
-        val initialPosition: Double
+        val initialDisplacement: Double
     ) {
         val dampingRatio: Double
             get() {
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 fc1cab6..f2758b6 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
@@ -30,17 +30,19 @@
         anim.toState(AnimState.B)
         val physicsAnim = SpringAnimation()
         var playTime = 0L
+        clock.clockTimeMillis = playTime
         do {
-            // Increment the time stamp until the animation finishes
-            clock.clockTimeMillis = playTime
             assertEquals(anim[prop1],
                 physicsAnim.getValue(playTime, 0f, 1f, 0f),
-                epsilon)
+                0.01f) // TODO(b/151115895) Replace placeholder delta with epsilon
 
             assertEquals(anim[prop2],
                 physicsAnim.getValue(playTime, 100f, -100f, 0f),
                 epsilon)
+
+            // Increment the time stamp until the animation finishes
             playTime += 20L
+            clock.clockTimeMillis = playTime
         } while (anim.isRunning)
     }
 
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
index c7501b8..b7ac545 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
@@ -29,10 +29,10 @@
 import androidx.compose.state
 import androidx.ui.animation.animatedFloat
 import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
 import androidx.ui.core.Text
 import androidx.ui.core.gesture.DragObserver
 import androidx.ui.core.gesture.RawDragGestureDetector
+import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
 import androidx.ui.foundation.Canvas
 import androidx.ui.foundation.CanvasScope
@@ -127,25 +127,23 @@
             }
         }) {
 
-            OnChildPositioned({ coordinates ->
+            val heightDp = with(DensityAmbient.current) { height.toDp() }
+            val paint = remember { Paint() }
+            Canvas(LayoutWidth.Fill + LayoutHeight(heightDp) + onPositioned { coordinates ->
                 itemWidth.value = coordinates.size.width.value * 2 / 3f
             }) {
-                val heightDp = with(DensityAmbient.current) { height.toDp() }
-                val paint = remember { Paint() }
-                Canvas(LayoutWidth.Fill + LayoutHeight(heightDp)) {
-                    val progress = 1 - itemBottom.value / height
-                    // TODO: this progress can be used to drive state transitions
-                    val alpha = 1f - FastOutSlowInEasing(progress)
-                    val horizontalOffset = progress * itemWidth.value
-                    drawLeftItems(
-                        paint, horizontalOffset, itemWidth.value, itemHeight, index.value
-                    )
-                    drawDismissingItem(
-                        paint,
-                        itemBottom.value, itemWidth.value, itemHeight, index.value + 1,
-                        alpha
-                    )
-                }
+                val progress = 1 - itemBottom.value / height
+                // TODO: this progress can be used to drive state transitions
+                val alpha = 1f - FastOutSlowInEasing(progress)
+                val horizontalOffset = progress * itemWidth.value
+                drawLeftItems(
+                    paint, horizontalOffset, itemWidth.value, itemHeight, index.value
+                )
+                drawDismissingItem(
+                    paint,
+                    itemBottom.value, itemWidth.value, itemHeight, index.value + 1,
+                    alpha
+                )
             }
         }
     }
diff --git a/ui/ui-foundation/api/0.1.0-dev07.txt b/ui/ui-foundation/api/0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/0.1.0-dev07.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev07.txt b/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -173,11 +173,11 @@
   public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
     ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
     method public float getAbsVelocityThreshold();
+    method public long getDurationMillis(float start, float startVelocity);
     method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
     method public float getTarget(float start, float startVelocity);
     method public float getValue(long playTime, float start, float startVelocity);
     method public float getVelocity(long playTime, float start, float startVelocity);
-    method public boolean isFinished(long playTime, float start, float startVelocity);
     property public float absVelocityThreshold;
     property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
   }
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
index 3a2f4da..9de1463 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
@@ -21,8 +21,8 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
 import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
 import androidx.ui.foundation.shape.RectangleShape
 import androidx.ui.foundation.shape.corner.CircleShape
 import androidx.ui.graphics.Color
@@ -64,9 +64,7 @@
         composeTestRule.setContent {
             SemanticsParent {
                 Box(LayoutSize(size), padding = padding) {
-                    OnChildPositioned({ childSize = it.size }) {
-                        Box(LayoutSize.Fill)
-                    }
+                    Box(LayoutSize.Fill + onPositioned { childSize = it.size })
                 }
             }
         }
@@ -95,12 +93,10 @@
                     paddingTop = top,
                     paddingBottom = bottom
                 ) {
-                    OnChildPositioned({
+                    Box(LayoutSize.Fill + onPositioned {
                         childSize = it.size
                         childPosition = it.localToGlobal(PxPosition.Origin)
-                    }) {
-                        Box(LayoutSize.Fill)
-                    }
+                    })
                 }
             }
         }
@@ -133,12 +129,10 @@
                     paddingTop = top,
                     paddingBottom = bottom
                 ) {
-                    OnChildPositioned({
+                    Box(LayoutSize.Fill + onPositioned {
                         childSize = it.size
                         childPosition = it.localToGlobal(PxPosition.Origin)
-                    }) {
-                        Box(LayoutSize.Fill)
-                    }
+                    })
                 }
             }
         }
@@ -170,9 +164,7 @@
                     paddingTop = top,
                     paddingBottom = bottom
                 ) {
-                    OnChildPositioned({ childSize = it.size }) {
-                        Box(LayoutSize.Fill)
-                    }
+                    Box(LayoutSize.Fill + onPositioned { childSize = it.size })
                 }
             }
         }
@@ -322,9 +314,7 @@
         composeTestRule.setContent {
             SemanticsParent {
                 Box(LayoutSize(size), border = Border(borderSize, Color.Red)) {
-                    OnChildPositioned({ childSize = it.size }) {
-                        Box(LayoutSize.Fill)
-                    }
+                    Box(LayoutSize.Fill + onPositioned { childSize = it.size })
                 }
             }
         }
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
index 5e12b39..ca53113 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
@@ -22,8 +22,8 @@
 import androidx.test.filters.SdkSuppress
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
-import androidx.ui.core.OnChildPositioned
 import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
 import androidx.ui.foundation.shape.RectangleShape
 import androidx.ui.foundation.shape.corner.CircleShape
 import androidx.ui.graphics.Color
@@ -76,10 +76,9 @@
         var canvasSize: IntPxSize? = null
         composeTestRule.setContentAndCollectSizes {
             SemanticParent {
-                OnChildPositioned({ position -> canvasSize = position.size }) {
-                    Canvas(modifier = LayoutSize(100.dp)) {
-                        drawRect(size.toRect(), Paint().apply { color = Color.Red })
-                    }
+                Canvas(modifier = LayoutSize(100.dp) +
+                        onPositioned { position -> canvasSize = position.size }) {
+                    drawRect(size.toRect(), Paint().apply { color = Color.Red })
                 }
             }
         }
@@ -103,14 +102,13 @@
         var canvasSize: IntPxSize? = null
         composeTestRule.setContentAndCollectSizes {
             SemanticParent {
-                OnChildPositioned({ position -> canvasSize = position.size }) {
-                    Canvas(modifier = LayoutSize(100.dp)) {
-                        drawRect(size.toRect(), Paint().apply { color = Color.Red })
-                        drawCircle(
-                            size.center().toOffset(),
-                            10f,
-                            Paint().apply { color = Color.Blue })
-                    }
+                Canvas(modifier = LayoutSize(100.dp) +
+                        onPositioned { position -> canvasSize = position.size }) {
+                    drawRect(size.toRect(), Paint().apply { color = Color.Red })
+                    drawCircle(
+                        size.center().toOffset(),
+                        10f,
+                        Paint().apply { color = Color.Blue })
                 }
             }
         }
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
index a4c7180..0646b29 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
@@ -17,7 +17,6 @@
 package androidx.ui.foundation.animation
 
 import androidx.animation.DecayAnimation
-import kotlin.math.roundToInt
 import kotlin.math.sign
 
 /**
@@ -43,13 +42,9 @@
     override fun getValue(playTime: Long, start: Float, startVelocity: Float): Float =
         start + flingCalculator.flingInfo(startVelocity).position(playTime)
 
+    override fun getDurationMillis(start: Float, startVelocity: Float): Long =
+        flingCalculator.flingDuration(startVelocity)
+
     override fun getVelocity(playTime: Long, start: Float, startVelocity: Float): Float =
         flingCalculator.flingInfo(startVelocity).velocity(playTime)
-
-    override fun isFinished(playTime: Long, start: Float, startVelocity: Float): Boolean {
-        val flingInfo = flingCalculator.flingInfo(startVelocity)
-        if (playTime > flingInfo.duration) return true
-
-        return flingInfo.distance.roundToInt() == flingInfo.position(playTime).roundToInt()
-    }
 }
\ No newline at end of file
diff --git a/ui/ui-framework/api/0.1.0-dev07.txt b/ui/ui-framework/api/0.1.0-dev07.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/0.1.0-dev07.txt
+++ b/ui/ui-framework/api/0.1.0-dev07.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/current.txt b/ui/ui-framework/api/current.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/current.txt
+++ b/ui/ui-framework/api/current.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/public_plus_experimental_current.txt b/ui/ui-framework/api/public_plus_experimental_current.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/public_plus_experimental_current.txt
+++ b/ui/ui-framework/api/public_plus_experimental_current.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/restricted_0.1.0-dev07.txt b/ui/ui-framework/api/restricted_0.1.0-dev07.txt
index eed64b91..4187b9a 100644
--- a/ui/ui-framework/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-framework/api/restricted_0.1.0-dev07.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/restricted_current.txt b/ui/ui-framework/api/restricted_current.txt
index eed64b91..4187b9a 100644
--- a/ui/ui-framework/api/restricted_current.txt
+++ b/ui/ui-framework/api/restricted_current.txt
@@ -75,7 +75,7 @@
   }
 
   public final class PasswordTextFieldKt {
-    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+    method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
   }
 
   public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
   }
 
   public final class TextFieldKt {
-    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
-    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit>  androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
+    method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit>  _, _ ->  }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit>  kotlin.jvm.functions.Function0<kotlin.Unit>  String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit>  androidx.ui.input.VisualTransformation? visualTransformation = null);
   }
 
   public final class TextKt {
     method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
-    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+    method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
     method public static androidx.ui.text.TextStyle currentTextStyle();
     method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
     method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
index f094c74..1ba6b89 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
@@ -62,7 +62,7 @@
     fun draw_selection_test() {
         val textDelegate = TextDelegate(
             text = AnnotatedString("Hello, World"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = 2,
             density = density,
             resourceLoader = resourceLoader,
@@ -103,7 +103,7 @@
 
         val textDelegate = TextDelegate(
             text = AnnotatedString("Hello, World"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = 2,
             density = density,
             resourceLoader = resourceLoader,
@@ -138,7 +138,7 @@
 
         val textDelegate = TextDelegate(
             text = AnnotatedString("Hello, World"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = 2,
             density = density,
             resourceLoader = resourceLoader,
@@ -169,7 +169,7 @@
     fun layout_height_constraint_max_height() {
         val textDelegate = TextDelegate(
             text = AnnotatedString("Hello, World"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = 2,
             density = density,
             resourceLoader = resourceLoader,
@@ -190,7 +190,7 @@
     fun layout_height_constraint_min_height() {
         val textDelegate = TextDelegate(
             text = AnnotatedString("Hello, World"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = 2,
             density = density,
             resourceLoader = resourceLoader,
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
index 74f5d42..3cfd025 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
@@ -23,10 +23,10 @@
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.text.TextLayoutResult
 import androidx.ui.text.TextStyle
-import androidx.ui.text.font.font
 import androidx.ui.text.font.FontStyle
 import androidx.ui.text.font.FontWeight
 import androidx.ui.text.font.asFontFamily
+import androidx.ui.text.font.font
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
@@ -72,18 +72,18 @@
         val textSize = Ref<IntPxSize>()
         val doubleTextSize = Ref<IntPxSize>()
         show {
-            OnChildPositioned({ coordinates ->
-                textSize.value = coordinates.size
-                layoutLatch.countDown()
-            }) {
-                Text("aa", style = TextStyle(fontFamily = fontFamily))
-            }
-            OnChildPositioned({ coordinates ->
-                doubleTextSize.value = coordinates.size
-                layoutLatch.countDown()
-            }) {
-                Text("aaaa", style = TextStyle(fontFamily = fontFamily))
-            }
+            Text("aa", style = TextStyle(fontFamily = fontFamily),
+                modifier = onPositioned { coordinates ->
+                    textSize.value = coordinates.size
+                    layoutLatch.countDown()
+                }
+            )
+            Text("aaaa", style = TextStyle(fontFamily = fontFamily),
+                modifier = onPositioned { coordinates ->
+                    doubleTextSize.value = coordinates.size
+                    layoutLatch.countDown()
+                }
+            )
         }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
         assertNotNull(textSize.value)
@@ -100,18 +100,18 @@
         val textSize = Ref<IntPxSize>()
         val doubleTextSize = Ref<IntPxSize>()
         show {
-            OnChildPositioned({ coordinates ->
-                textSize.value = coordinates.size
-                layoutLatch.countDown()
-            }) {
-                Text("aa ", style = TextStyle(fontFamily = fontFamily))
-            }
-            OnChildPositioned({ coordinates ->
-                doubleTextSize.value = coordinates.size
-                layoutLatch.countDown()
-            }) {
-                Text("aa aa ", style = TextStyle(fontFamily = fontFamily))
-            }
+            Text("aa ", style = TextStyle(fontFamily = fontFamily),
+                modifier = onPositioned { coordinates ->
+                    textSize.value = coordinates.size
+                    layoutLatch.countDown()
+                }
+            )
+            Text("aa aa ", style = TextStyle(fontFamily = fontFamily),
+                modifier = onPositioned { coordinates ->
+                    doubleTextSize.value = coordinates.size
+                    layoutLatch.countDown()
+                }
+            )
         }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
         val textWidth = textSize.value!!.width
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index 98229b9..95c3f96 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -45,7 +45,6 @@
 import androidx.ui.core.LayoutTag
 import androidx.ui.core.Measurable
 import androidx.ui.core.Modifier
-import androidx.ui.core.OnPositioned
 import androidx.ui.core.ParentData
 import androidx.ui.core.ParentDataModifier
 import androidx.ui.core.Ref
@@ -55,6 +54,7 @@
 import androidx.ui.core.drawWithContent
 import androidx.ui.core.globalPosition
 import androidx.ui.core.offset
+import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
 import androidx.ui.core.tag
 import androidx.ui.framework.test.TestActivity
@@ -1694,18 +1694,18 @@
                 SimpleRow {
                     for (i in 0 until 2) {
                         if (model.offset.value == i) {
-                            Wrap(minWidth = size, minHeight = size) {
-                                OnPositioned { coordinates ->
+                            Wrap(minWidth = size, minHeight = size,
+                                modifier = onPositioned { coordinates ->
                                     wrap1Position = coordinates.globalPosition.x
                                     latch.countDown()
-                                }
+                                }) {
                             }
                         } else {
-                            Wrap(minWidth = size, minHeight = size) {
-                                OnPositioned { coordinates ->
+                            Wrap(minWidth = size, minHeight = size,
+                                modifier = onPositioned { coordinates ->
                                     wrap2Position = coordinates.globalPosition.x
                                     latch.countDown()
-                                }
+                                }) {
                             }
                         }
                     }
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
index 8d40221..417a19f 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
@@ -22,8 +22,9 @@
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutDirection
 import androidx.ui.core.LayoutModifier
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.Modifier
 import androidx.ui.core.Ref
+import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
 import androidx.ui.unit.Density
 import androidx.ui.unit.PxPosition
@@ -137,14 +138,11 @@
         }
         Layout(
             children = @Composable {
-                FixedSize(size) {
-                    SaveLayoutInfo(position[0], countDownLatch)
+                FixedSize(size, modifier = saveLayoutInfo(position[0], countDownLatch)) {
                 }
-                FixedSize(size) {
-                    SaveLayoutInfo(position[1], countDownLatch)
+                FixedSize(size, modifier = saveLayoutInfo(position[1], countDownLatch)) {
                 }
-                FixedSize(size) {
-                    SaveLayoutInfo(position[2], countDownLatch)
+                FixedSize(size, modifier = saveLayoutInfo(position[2], countDownLatch)) {
                 }
             },
             modifier = modifier
@@ -169,10 +167,11 @@
     }
 
     @Composable
-    private fun SaveLayoutInfo(position: Ref<PxPosition>, countDownLatch: CountDownLatch) {
-        OnPositioned {
-            position.value = it.localToGlobal(PxPosition(0.ipx, 0.ipx))
-            countDownLatch.countDown()
-        }
+    private fun saveLayoutInfo(
+        position: Ref<PxPosition>,
+        countDownLatch: CountDownLatch
+    ): Modifier = onPositioned {
+        position.value = it.localToGlobal(PxPosition(0.ipx, 0.ipx))
+        countDownLatch.countDown()
     }
 }
\ No newline at end of file
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
index 3b3ebc0..b495d89 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
@@ -31,10 +31,10 @@
 import androidx.ui.core.LayoutModifier
 import androidx.ui.core.MeasureBlock
 import androidx.ui.core.Modifier
-import androidx.ui.core.OnPositioned
 import androidx.ui.core.Ref
 import androidx.ui.core.WithConstraints
 import androidx.ui.core.draw
+import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.graphics.Color
@@ -308,24 +308,23 @@
         rule.runOnUiThreadIR {
             activity.setContentInFrameLayout {
                 Container(width = 200.ipx, height = 200.ipx) {
-                    WithConstraints { _, _ ->
-                        OnPositioned {
-                            // OnPositioned can be fired multiple times with the same value
-                            // for example when requestLayout() was triggered on ComposeView.
-                            // if we called twice, let's make sure we got the correct values.
-                            assertTrue(withConstSize == null || withConstSize == it.size)
-                            withConstSize = it.size
-                            withConstLatch.countDown()
-                        }
-                        Container(width = size.value, height = size.value) {
-                            OnPositioned {
+                    WithConstraints(modifier = onPositioned {
+                        // OnPositioned can be fired multiple times with the same value
+                        // for example when requestLayout() was triggered on ComposeView.
+                        // if we called twice, let's make sure we got the correct values.
+                        assertTrue(withConstSize == null || withConstSize == it.size)
+                        withConstSize = it.size
+                        withConstLatch.countDown()
+                    }) { _, _ ->
+                        Container(width = size.value, height = size.value,
+                            modifier = onPositioned {
                                 // OnPositioned can be fired multiple times with the same value
                                 // for example when requestLayout() was triggered on ComposeView.
                                 // if we called twice, let's make sure we got the correct values.
                                 assertTrue(childSize == null || childSize == it.size)
                                 childSize = it.size
                                 childLatch.countDown()
-                            }
+                            }) {
                         }
                     }
                 }
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt b/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
index baa557e..ab081e3 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
@@ -63,7 +63,7 @@
 fun PasswordTextField(
     value: String,
     onValueChange: (String) -> Unit = {},
-    textStyle: TextStyle? = null,
+    textStyle: TextStyle = TextStyle.Default,
     mask: Char = '\u2022',
     imeAction: ImeAction = ImeAction.Unspecified,
     onFocus: () -> Unit = {},
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt b/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
index a2c5b69..38c30bb 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
@@ -19,6 +19,7 @@
 import androidx.compose.Providers
 import androidx.compose.StructurallyEqual
 import androidx.compose.ambientOf
+import androidx.compose.emptyContent
 import androidx.compose.mutableStateOf
 import androidx.compose.onCommit
 import androidx.compose.remember
@@ -70,7 +71,7 @@
 fun Text(
     text: String,
     modifier: Modifier = Modifier.None,
-    style: TextStyle? = null,
+    style: TextStyle = TextStyle.Default,
     softWrap: Boolean = DefaultSoftWrap,
     overflow: TextOverflow = DefaultOverflow,
     maxLines: Int = DefaultMaxLines,
@@ -107,7 +108,7 @@
 fun Text(
     text: AnnotatedString,
     modifier: Modifier = Modifier.None,
-    style: TextStyle? = null,
+    style: TextStyle = TextStyle.Default,
     softWrap: Boolean = DefaultSoftWrap,
     overflow: TextOverflow = DefaultOverflow,
     maxLines: Int = DefaultMaxLines,
@@ -165,36 +166,32 @@
                 state.textDelegate.paint(canvas, layoutResult)
             }
         }
-        val children = @Composable {
-            // Get the layout coordinates of the text composable. This is for hit test of
-            // cross-composable selection.
-            OnPositioned(
-                >
-                    val oldLayoutCoordinates = state.layoutCoordinates
-                    state.layoutCoordinates = it
+        // Get the layout coordinates of the text composable. This is for hit test of
+        // cross-composable selection.
+        val  {
+            val oldLayoutCoordinates = state.layoutCoordinates
+            state.layoutCoordinates = it
 
-                    if ((oldLayoutCoordinates == null || !oldLayoutCoordinates.isAttached) &&
-                        it.isAttached
-                    ) {
-                        selectionRegistrar?.onPositionChange()
-                    }
+            if ((oldLayoutCoordinates == null || !oldLayoutCoordinates.isAttached) &&
+                it.isAttached
+            ) {
+                selectionRegistrar?.onPositionChange()
+            }
 
-                    if (oldLayoutCoordinates != null && oldLayoutCoordinates.isAttached &&
-                        it.isAttached
-                    ) {
-                        if (
-                            oldLayoutCoordinates.localToGlobal(PxPosition.Origin) !=
-                            it.localToGlobal(PxPosition.Origin)
-                        ) {
-                            selectionRegistrar?.onPositionChange()
-                        }
-                    }
+            if (oldLayoutCoordinates != null && oldLayoutCoordinates.isAttached &&
+                it.isAttached
+            ) {
+                if (
+                    oldLayoutCoordinates.localToGlobal(PxPosition.Origin) !=
+                    it.localToGlobal(PxPosition.Origin)
+                ) {
+                    selectionRegistrar?.onPositionChange()
                 }
-            )
+            }
         }
         Layout(
-            children = children,
-            modifier = modifier + textDrawModifier,
+            children = emptyContent(),
+            modifier = modifier + textDrawModifier + onPositioned,
             minIntrinsicWidthMeasureBlock = { _, _, _ ->
                 state.textDelegate.layoutIntrinsics()
                 state.textDelegate.minIntrinsicWidth
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt b/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
index 8422f4a..b8d1150 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
@@ -16,6 +16,7 @@
 package androidx.ui.core
 
 import androidx.compose.Composable
+import androidx.compose.emptyContent
 import androidx.compose.mutableStateOf
 import androidx.compose.onDispose
 import androidx.compose.remember
@@ -94,7 +95,7 @@
     value: String,
     modifier: Modifier = Modifier.None,
     onValueChange: (String) -> Unit = {},
-    textStyle: TextStyle? = null,
+    textStyle: TextStyle = TextStyle.Default,
     keyboardType: KeyboardType = KeyboardType.Text,
     imeAction: ImeAction = ImeAction.Unspecified,
     onFocus: () -> Unit = {},
@@ -187,7 +188,7 @@
     value: TextFieldValue,
     modifier: Modifier = Modifier.None,
     onValueChange: (TextFieldValue) -> Unit = {},
-    textStyle: TextStyle? = null,
+    textStyle: TextStyle = TextStyle.Default,
     keyboardType: KeyboardType = KeyboardType.Text,
     imeAction: ImeAction = ImeAction.Unspecified,
     onFocus: () -> Unit = {},
@@ -286,7 +287,7 @@
     compositionRange: TextRange?,
     modifier: Modifier = Modifier.None,
     onValueChange: (TextFieldValue, TextRange?) -> Unit = { _, _ -> },
-    textStyle: TextStyle? = null,
+    textStyle: TextStyle = TextStyle.Default,
     keyboardType: KeyboardType = KeyboardType.Text,
     imeAction: ImeAction = ImeAction.Unspecified,
     onFocus: () -> Unit = {},
@@ -318,7 +319,7 @@
     value: InputState,
     modifier: Modifier,
     onValueChange: (InputState) -> Unit = { },
-    textStyle: TextStyle? = null,
+    textStyle: TextStyle = TextStyle.Default,
     keyboardType: KeyboardType = KeyboardType.Text,
     imeAction: ImeAction = ImeAction.Unspecified,
     onFocus: () -> Unit = {},
@@ -403,12 +404,13 @@
                 }
                 onFocus()
             },
-            >
+             hasNextClient ->
                 state.hasFocus = false
                 TextFieldDelegate.onBlur(
                     textInputService,
                     state.inputSession,
                     state.processor,
+                    hasNextClient,
                     onValueChangeWrapper)
                 onBlur()
             },
@@ -440,26 +442,25 @@
                 }
             }
             Layout(
-                modifier = modifier + textDrawModifier,
-                children = @Composable {
-                    OnPositioned {
-                        if (textInputService != null) {
-                            state.layoutCoordinates = it
-                            state.layoutResult?.let { layoutResult ->
-                                TextFieldDelegate.notifyFocusedRect(
-                                    value,
-                                    state.textDelegate,
-                                    layoutResult,
-                                    it,
-                                    textInputService,
-                                    state.inputSession,
-                                    state.hasFocus,
-                                    offsetMap
-                                )
+                modifier = modifier + textDrawModifier +
+                        onPositioned {
+                            if (textInputService != null) {
+                                state.layoutCoordinates = it
+                                state.layoutResult?.let { layoutResult ->
+                                    TextFieldDelegate.notifyFocusedRect(
+                                        value,
+                                        state.textDelegate,
+                                        layoutResult,
+                                        it,
+                                        textInputService,
+                                        state.inputSession,
+                                        state.hasFocus,
+                                        offsetMap
+                                    )
+                                }
                             }
-                        }
-                    }
-                },
+                        },
+                children = emptyContent(),
                 measureBlock = { _, constraints, _ ->
                     TextFieldDelegate.layout(
                         state.textDelegate,
@@ -499,7 +500,7 @@
     onPress: (PxPosition) -> Unit,
     onRelease: (PxPosition) -> Unit,
     onFocus: () -> Unit,
-    onBlur: () -> Unit,
+    onBlur: (hasNextClient: Boolean) -> Unit,
     focusIdentifier: String?,
     children: @Composable() () -> Unit
 ) {
@@ -513,8 +514,8 @@
                 focused.value = true
             }
 
-            override fun onBlur() {
-                onBlur()
+            override fun onBlur(hasNextClient: Boolean) {
+                onBlur(hasNextClient)
                 focused.value = false
             }
         }
@@ -526,6 +527,9 @@
     }
 
     onDispose {
+        if (focused.value) {
+            focusManager.blur(focusNode)
+        }
         if (focusIdentifier != null)
             focusManager.unregisterFocusNode(focusIdentifier)
     }
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt b/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
index 0668307..0b85806 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
@@ -325,10 +325,14 @@
             textInputService: TextInputService?,
             token: InputSessionToken,
             editProcessor: EditProcessor,
+            hasNextClient: Boolean,
             onValueChange: (InputState) -> Unit
         ) {
             onEditCommand(listOf(FinishComposingTextEditOp()), editProcessor, onValueChange)
             textInputService?.stopInput(token)
+            if (!hasNextClient) {
+                textInputService?.hideSoftwareKeyboard(token)
+            }
         }
 
         /**
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt b/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
index 759525f..8b91c7f 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
@@ -30,8 +30,13 @@
         /** Called when this component gained the focus */
         fun onFocus()
 
-        /** Called when this component is about to lose the focus */
-        fun onBlur()
+        /**
+         *  Called when this component is about to lose the focus
+         *
+         *  @param hasNextClient True if this node loses focus due to focusing in to another node
+         *  . False if this node loses focus due to calling [FocusManager#blur].
+         */
+        fun onBlur(hasNextClient: Boolean)
     }
 
     /**
@@ -84,18 +89,20 @@
         }
 
         if (currentFocus != null) {
-            focusOut(currentFocus)
+            currentFocus.onBlur(true)
         }
 
         focusedClient = client
-        focusIn(client)
-    }
-
-    private fun focusIn(client: FocusNode) {
         client.onFocus()
     }
 
-    private fun focusOut(client: FocusNode) {
-        client.onBlur()
+    /**
+     * Release the focus if given focus node is focused
+     */
+    internal fun blur(client: FocusNode) {
+        if (focusedClient == client) {
+            focusedClient = null
+            client.onBlur(false)
+        }
     }
 }
\ No newline at end of file
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
index ccfdc53..ef1d756 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
@@ -24,7 +24,7 @@
 import androidx.ui.core.Constraints
 import androidx.ui.core.HapticFeedBackAmbient
 import androidx.ui.core.Layout
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.Modifier
 import androidx.ui.core.Placeable
 import androidx.ui.core.Popup
 import androidx.ui.core.enforce
@@ -33,6 +33,7 @@
 import androidx.ui.core.gesture.TouchSlopDragGestureDetector
 import androidx.ui.core.hasFixedHeight
 import androidx.ui.core.hasFixedWidth
+import androidx.ui.core.onPositioned
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
@@ -78,10 +79,9 @@
     manager.selection = selection
 
     Providers(SelectionRegistrarAmbient provides registrarImpl) {
-        Wrap {
-            // Get the layout coordinates of the selection container. This is for hit test of
-            // cross-composable selection.
-            OnPositioned( manager.containerLayoutCoordinates = it })
+        // Get the layout coordinates of the selection container. This is for hit test of
+        // cross-composable selection.
+        Wrap(onPositioned { manager.containerLayoutCoordinates = it }) {
             PressReleasedGestureDetector( manager.onRelease() }) {
                 LongPressDragGestureDetector(manager.longPressDragObserver, children = children)
             }
@@ -164,8 +164,8 @@
  * the children.
  */
 @Composable
-private fun Wrap(children: @Composable() () -> Unit) {
-    Layout(children) { measurables, constraints, _ ->
+private fun Wrap(modifier: Modifier = Modifier.None, children: @Composable() () -> Unit) {
+    Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
         val placeables = measurables.map { measurable ->
             measurable.measure(constraints)
         }
diff --git a/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt b/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
index e1f5e22..75342f1 100644
--- a/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
+++ b/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
@@ -194,12 +194,39 @@
 
         whenever(processor.onEditCommands(captor.capture())).thenReturn(InputState())
 
-        TextFieldDelegate.onBlur(textInputService, dummyInputSessionToken, processor, onValueChange)
+        TextFieldDelegate.onBlur(
+            textInputService,
+            dummyInputSessionToken,
+            processor,
+            true,
+            onValueChange)
 
         assertEquals(1, captor.allValues.size)
         assertEquals(1, captor.firstValue.size)
         assertTrue(captor.firstValue[0] is FinishComposingTextEditOp)
         verify(textInputService).stopInput(eq(dummyInputSessionToken))
+        verify(textInputService, never()).hideSoftwareKeyboard(any())
+    }
+
+    @Test
+    fun on_blur_with_hiding() {
+        val captor = argumentCaptor<List<EditOperation>>()
+        val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
+
+        whenever(processor.onEditCommands(captor.capture())).thenReturn(InputState())
+
+        TextFieldDelegate.onBlur(
+            textInputService,
+            dummyInputSessionToken,
+            processor,
+            false, // There is no next focused client. Hide the keyboard.
+            onValueChange)
+
+        assertEquals(1, captor.allValues.size)
+        assertEquals(1, captor.firstValue.size)
+        assertTrue(captor.firstValue[0] is FinishComposingTextEditOp)
+        verify(textInputService).stopInput(eq(dummyInputSessionToken))
+        verify(textInputService).hideSoftwareKeyboard(eq(dummyInputSessionToken))
     }
 
     @Test
diff --git a/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt b/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
index 2785335..a5dca661 100644
--- a/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
+++ b/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.ui.core.input
 
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.eq
 import com.nhaarman.mockitokotlin2.inOrder
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.never
@@ -35,7 +37,7 @@
         fm.requestFocus(FocusNode1)
 
         verify(FocusNode1, times(1)).onFocus()
-        verify(FocusNode1, never()).onBlur()
+        verify(FocusNode1, never()).onBlur(eq(true /* hasNextClient */))
     }
 
     @Test
@@ -50,7 +52,7 @@
         // onBlur must be called to currently focused object, then onFocus is called to the next
         // object.
         inOrder(FocusNode1, FocusNode2) {
-            verify(FocusNode1, times(1)).onBlur()
+            verify(FocusNode1, times(1)).onBlur(eq(true /* hasNextClient */))
             verify(FocusNode2, times(1)).onFocus()
         }
     }
@@ -62,12 +64,12 @@
         val fm = FocusManager()
         fm.requestFocus(FocusNode1)
         verify(FocusNode1, times(1)).onFocus()
-        verify(FocusNode1, never()).onBlur()
+        verify(FocusNode1, never()).onBlur(any())
 
         // Either onFocus or onBlur must not be called for the already focused object.
         fm.requestFocus(FocusNode1)
         verify(FocusNode1, times(1)).onFocus()
-        verify(FocusNode1, never()).onBlur()
+        verify(FocusNode1, never()).onBlur(any())
     }
 
     @Test
@@ -80,7 +82,7 @@
         fm.registerFocusNode(id, node)
         fm.requestFocusById(id)
         verify(node, times(1)).onFocus()
-        verify(node, never()).onBlur()
+        verify(node, never()).onBlur(any())
     }
 
     @Test
@@ -95,6 +97,19 @@
         fm.unregisterFocusNode(id)
         fm.requestFocusById(id)
         verify(node, never()).onFocus()
-        verify(node, never()).onBlur()
+        verify(node, never()).onBlur(any())
+    }
+
+    @Test
+    fun blur() {
+        val focusNode: FocusManager.FocusNode = mock()
+
+        val fm = FocusManager()
+        fm.requestFocus(focusNode)
+
+        // onBlur must be called to currently focused object, then onFocus is called to the next
+        // object.
+        fm.blur(focusNode)
+        verify(focusNode, times(1)).onBlur(eq(false /* hasNextClient */))
     }
 }
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
index 3685b3b..ade1767 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
@@ -19,9 +19,9 @@
 import androidx.ui.core.LastBaseline
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
 import androidx.ui.core.Text
 import androidx.ui.core.globalPosition
+import androidx.ui.core.onPositioned
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.Icon
 import androidx.ui.material.icons.Icons
@@ -59,10 +59,11 @@
         lateinit var parentCoords: LayoutCoordinates
         val height = 56.dp
         composeTestRule
-            .setMaterialContentAndCollectSizes {
-                OnPositioned { coords ->
+            .setMaterialContentAndCollectSizes(modifier =
+                onPositioned { coords ->
                     parentCoords = coords
                 }
+            ) {
                 BottomNavigationSample()
             }
             .assertWidthEqualsTo { parentCoords.size.width }
@@ -73,10 +74,9 @@
     fun bottomNavigationItem_sizeAndPositions() {
         lateinit var parentCoords: LayoutCoordinates
         val itemCoords = mutableMapOf<Int, LayoutCoordinates>()
-        composeTestRule.setMaterialContent {
-            OnPositioned { coords ->
-                parentCoords = coords
-            }
+        composeTestRule.setMaterialContent(modifier = onPositioned { coords ->
+            parentCoords = coords
+        }) {
             Box {
                 BottomNavigation {
                     repeat(4) { index ->
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
index fef24de..b0cf66c 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
@@ -20,11 +20,11 @@
 import androidx.compose.state
 import androidx.test.filters.MediumTest
 import androidx.ui.core.LayoutCoordinates
-import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
 import androidx.ui.core.TestTag
 import androidx.ui.core.Text
 import androidx.ui.core.currentTextStyle
+import androidx.ui.core.onChildPositioned
+import androidx.ui.core.onPositioned
 import androidx.ui.layout.Center
 import androidx.ui.layout.Column
 import androidx.ui.layout.Stack
@@ -291,16 +291,9 @@
         var parentCoordinates: LayoutCoordinates? = null
         var childCoordinates: LayoutCoordinates? = null
         composeTestRule.setMaterialContent {
-            Stack {
+            Stack(onChildPositioned { parentCoordinates = it }) {
                 button {
-                    OnPositioned {
-                        parentCoordinates = it
-                    }
-                    OnChildPositioned(>
-                        childCoordinates = it
-                    }) {
-                        Text("Test button")
-                    }
+                    Text("Test button", onPositioned { childCoordinates = it })
                 }
             }
         }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
index bef16f7..7bf194e 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
@@ -21,8 +21,8 @@
 import androidx.compose.emptyContent
 import androidx.test.filters.MediumTest
 import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
 import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
 import androidx.ui.foundation.Clickable
 import androidx.ui.layout.Container
 import androidx.ui.semantics.Semantics
@@ -64,10 +64,9 @@
         var position: PxPosition? = null
         composeTestRule.setMaterialContent {
             ModalDrawerLayout(DrawerState.Opened, {}, drawerContent = {
-                Container(expanded = true) {
-                    OnPositioned { coords ->
-                        position = coords.localToGlobal(PxPosition.Origin)
-                    }
+                Container(onPositioned { coords ->
+                    position = coords.localToGlobal(PxPosition.Origin)
+                }, expanded = true) {
                 }
             }, bodyContent = emptyContent())
         }
@@ -81,10 +80,9 @@
         var position: PxPosition? = null
         composeTestRule.setMaterialContent {
             ModalDrawerLayout(DrawerState.Closed, {}, drawerContent = {
-                Container(expanded = true) {
-                    OnPositioned { coords ->
-                        position = coords.localToGlobal(PxPosition.Origin)
-                    }
+                Container(onPositioned { coords ->
+                    position = coords.localToGlobal(PxPosition.Origin)
+                }, expanded = true) {
                 }
             }, bodyContent = emptyContent())
         }
@@ -99,10 +97,9 @@
         var size: IntPxSize? = null
         composeTestRule.setMaterialContent {
             ModalDrawerLayout(DrawerState.Opened, {}, drawerContent = {
-                Container(expanded = true) {
-                    OnPositioned { coords ->
-                        size = coords.size
-                    }
+                Container(onPositioned { coords ->
+                    size = coords.size
+                }, expanded = true) {
                 }
             }, bodyContent = emptyContent())
         }
@@ -119,10 +116,9 @@
         var position: PxPosition? = null
         composeTestRule.setMaterialContent {
             BottomDrawerLayout(DrawerState.Opened, {}, drawerContent = {
-                Container(expanded = true) {
-                    OnPositioned { coords ->
-                        position = coords.localToGlobal(PxPosition.Origin)
-                    }
+                Container(onPositioned { coords ->
+                    position = coords.localToGlobal(PxPosition.Origin)
+                }, expanded = true) {
                 }
             }, bodyContent = emptyContent())
         }
@@ -141,10 +137,9 @@
         var position: PxPosition? = null
         composeTestRule.setMaterialContent {
             BottomDrawerLayout(DrawerState.Closed, {}, drawerContent = {
-                Container(expanded = true) {
-                    OnPositioned { coords ->
-                        position = coords.localToGlobal(PxPosition.Origin)
-                    }
+                Container(onPositioned { coords ->
+                    position = coords.localToGlobal(PxPosition.Origin)
+                }, expanded = true) {
                 }
             }, bodyContent = emptyContent())
         }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
index 07bf5f7..1f0cf5d 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
@@ -17,6 +17,7 @@
 package androidx.ui.material
 
 import androidx.compose.Composable
+import androidx.ui.core.Modifier
 import androidx.ui.layout.DpConstraints
 import androidx.ui.test.BigTestConstraints
 import androidx.ui.test.CollectedSizes
@@ -25,10 +26,13 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.PxSize
 
-fun ComposeTestRule.setMaterialContent(composable: @Composable() () -> Unit) {
+fun ComposeTestRule.setMaterialContent(
+    modifier: Modifier = Modifier.None,
+    composable: @Composable() () -> Unit
+) {
     setContent {
         MaterialTheme {
-            Surface(children = composable)
+            Surface(modifier = modifier, children = composable)
         }
     }
 }
@@ -38,21 +42,23 @@
     }
 }
 fun ComposeTestRule.setMaterialContentAndCollectSizes(
+    modifier: Modifier = Modifier.None,
     parentConstraints: DpConstraints = BigTestConstraints,
     children: @Composable() () -> Unit
 ): CollectedSizes {
-    val sizes = setMaterialContentAndGetPixelSize(parentConstraints, children)
+    val sizes = setMaterialContentAndGetPixelSize(modifier, parentConstraints, children)
     return CollectedSizes(sizes, density)
 }
 
 fun ComposeTestRule.setMaterialContentAndGetPixelSize(
+    modifier: Modifier = Modifier.None,
     parentConstraints: DpConstraints = BigTestConstraints,
     children: @Composable() () -> Unit
 ): PxSize = setContentAndGetPixelSize(
     parentConstraints,
-    { setMaterialContent(it) }
+    { setMaterialContent(composable = it) }
 ) {
     MaterialTheme {
-        Surface(children = children)
+        Surface(modifier = modifier, children = children)
     }
 }
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
index 813992e..70d9631 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
@@ -107,7 +107,7 @@
 
         composeTestRule
             .setMaterialContentAndCollectSizes(
-                DpConstraints(maxWidth = 100.dp, maxHeight = 100.dp)
+                parentConstraints = DpConstraints(maxWidth = 100.dp, maxHeight = 100.dp)
             ) { Slider(position) }
             .assertHeightEqualsTo(48.dp)
             .assertWidthEqualsTo(100.dp)
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
index 07ba3cd..633c146 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
@@ -147,7 +147,7 @@
         if (icon == null) {
             Text(
                 text = text,
-                style = textStyle,
+                style = textStyle ?: TextStyle.Default,
                 modifier = LayoutPadding(
                     start = ExtendedFabTextPadding,
                     end = ExtendedFabTextPadding
@@ -157,7 +157,7 @@
             Row(LayoutPadding(start = ExtendedFabIconPadding, end = ExtendedFabTextPadding)) {
                 Image(image = icon)
                 Spacer(LayoutWidth(ExtendedFabIconPadding))
-                Text(text = text, style = textStyle)
+                Text(text = text, style = textStyle ?: TextStyle.Default)
             }
         }
     }
diff --git a/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt b/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
index 6f443a1..60c86f1 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
@@ -106,12 +106,17 @@
         >
 
         imm.restartInput(view)
+        editorHasFocus = false
     }
 
     override fun showSoftwareKeyboard() {
         imm.showSoftInput(view, 0)
     }
 
+    override fun hideSoftwareKeyboard() {
+        imm.hideSoftInputFromWindow(view.windowToken, 0)
+    }
+
     override fun onStateUpdated(model: InputState) {
         this.state = model
         ic?.updateInputState(this.state, imm, view)
diff --git a/ui/ui-saved-instance-state/OWNERS b/ui/ui-saved-instance-state/OWNERS
new file mode 100644
index 0000000..5b1abd9
--- /dev/null
+++ b/ui/ui-saved-instance-state/OWNERS
@@ -0,0 +1 @@
+andreykulikov@google.com
\ No newline at end of file
diff --git a/ui/ui-saved-instance-state/api/0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/current.txt b/ui/ui-saved-instance-state/api/current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt b/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt
diff --git a/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/restricted_current.txt b/ui/ui-saved-instance-state/api/restricted_current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/restricted_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+  public interface UiSavedStateRegistry {
+    method public boolean canBeSaved(Object value);
+    method public Object? consumeRestored(String key);
+    method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+    method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+    method public void unregisterProvider(String key);
+  }
+
+  public final class UiSavedStateRegistryKt {
+    method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+  }
+
+}
+
diff --git a/ui/ui-saved-instance-state/build.gradle b/ui/ui-saved-instance-state/build.gradle
new file mode 100644
index 0000000..a42851c
--- /dev/null
+++ b/ui/ui-saved-instance-state/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("AndroidXUiPlugin")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    kotlinPlugin project(path: ":compose:compose-compiler")
+
+    implementation(KOTLIN_STDLIB)
+
+    api "androidx.annotation:annotation:1.1.0"
+
+    api project(":compose:compose-runtime")
+
+    testImplementation(ANDROIDX_TEST_RULES)
+    testImplementation(ANDROIDX_TEST_RUNNER)
+    testImplementation(JUNIT)
+    testImplementation(TRUTH)
+}
+
+androidx {
+    name = "Compose Saved Instance State support"
+    publish = Publish.SNAPSHOT_AND_RELEASE
+    mavenVersion = LibraryVersions.UI
+    mavenGroup = LibraryGroups.UI
+    inceptionYear = "2020"
+    description = "Compose components that allows to save and restore the ui local state"
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        useIR = true
+    }
+}
diff --git a/ui/ui-saved-instance-state/src/main/AndroidManifest.xml b/ui/ui-saved-instance-state/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bb92a23
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<manifest package="androidx.ui.savedinstancestate" />
diff --git a/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt b/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
new file mode 100644
index 0000000..f4aaeb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.ui.savedinstancestate
+
+/**
+ * Allows components to save and restore their state using the saved instance state mechanism.
+ */
+interface UiSavedStateRegistry {
+    /**
+     * Returns the restored value for the given key.
+     * Once being restored the value is cleared, so you can't restore the same key twice.
+     *
+     * @param key Key used to save the value
+     */
+    fun consumeRestored(key: String): Any?
+
+    /**
+     * Registers the value provider.
+     *
+     * The same [key] cannot be registered twice, if you need to update the provider call
+     * [unregisterProvider] first and then register again.
+     *
+     * @param key Key to use for storing the value
+     * @param valueProvider Provides the current value, to be executed when [performSave]
+     * will be triggered to collect all the registered values
+     */
+    fun registerProvider(key: String, valueProvider: () -> Any?)
+
+    /**
+     * Unregisters the value provider previously registered via [registerProvider].
+     *
+     * @param key Key of the value which shouldn't be saved anymore
+     */
+    fun unregisterProvider(key: String)
+
+    /**
+     * Returns true if the value can be saved using this Registry.
+     * The default implementation will return true if this value can be stored in Bundle.
+     *
+     * @param value The value which we want to save using this Registry
+     */
+    fun canBeSaved(value: Any): Boolean
+
+    /**
+     * Executes all the registered value providers and combines these values into a key-value map.
+     */
+    fun performSave(): Map<String, Any>
+}
+
+/**
+ * Creates [UiSavedStateRegistry].
+ *
+ * @param restoredValues The map of the restored values
+ * @param canBeSaved Function which returns true if the given value can be saved by the registry
+ */
+fun UiSavedStateRegistry(
+    restoredValues: Map<String, Any>?,
+    canBeSaved: (Any) -> Boolean
+): UiSavedStateRegistry = UiSavedStateRegistryImpl(restoredValues, canBeSaved)
+
+private class UiSavedStateRegistryImpl(
+    restored: Map<String, Any>?,
+    private val canBeSaved: (Any) -> Boolean
+) : UiSavedStateRegistry {
+
+    private val restored: MutableMap<String, Any> = restored?.toMutableMap() ?: mutableMapOf()
+    private val valueProviders = mutableMapOf<String, () -> Any?>()
+
+    override fun canBeSaved(value: Any): Boolean = canBeSaved.invoke(value)
+
+    override fun consumeRestored(key: String): Any? = restored.remove(key)
+
+    override fun registerProvider(key: String, valueProvider: () -> Any?) {
+        require(key.isNotBlank()) { "Registered key is empty or blank" }
+        require(!valueProviders.contains(key)) {
+            "Key $key was already registered. Please call " +
+                    "unregister before registering again"
+        }
+        @Suppress("UNCHECKED_CAST")
+        valueProviders[key] = valueProvider
+    }
+
+    override fun unregisterProvider(key: String) {
+        require(valueProviders.contains(key)) {
+            "Key $key wasn't registered, but unregister " +
+                    "requested"
+        }
+        valueProviders.remove(key)
+    }
+
+    override fun performSave(): Map<String, Any> {
+        val map = restored.toMutableMap()
+        valueProviders.forEach {
+            val value = it.value()
+            if (value != null) {
+                check(canBeSaved(value))
+                map[it.key] = value
+            }
+        }
+        return map
+    }
+}
diff --git a/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt b/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt
new file mode 100644
index 0000000..d175ee9
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt
@@ -0,0 +1,176 @@
+/*
+ * 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.ui.savedinstancestate
+
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class UiSavedStateRegistryTest {
+
+    @Test
+    fun saveSimpleValue() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key") { 10 }
+
+        registry.performSave().apply {
+            assertThat(get("key")).isEqualTo(10)
+        }
+    }
+
+    @Test
+    fun unregisteredValuesAreNotSaved() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key") { 10 }
+        registry.unregisterProvider("key")
+
+        registry.performSave().apply {
+            assertThat(containsKey("key")).isFalse()
+        }
+    }
+
+    @Test
+    fun registerAgainAfterUnregister() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key") { "value1" }
+        registry.unregisterProvider("key")
+        registry.registerProvider("key") { "value2" }
+
+        registry.performSave().apply {
+            assertThat(get("key")).isEqualTo("value2")
+        }
+    }
+
+    @Test
+    fun registerMultipleValues() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key1") { 100L }
+        registry.registerProvider("key2") { 100L }
+        registry.registerProvider("key3") { "value" }
+        registry.registerProvider("key4") { listOf("item") }
+        registry.unregisterProvider("key2")
+
+        registry.performSave().apply {
+            assertThat(get("key1")).isEqualTo(100L)
+            assertThat(containsKey("key2")).isFalse()
+            assertThat(get("key3")).isEqualTo("value")
+            assertThat(get("key4")).isEqualTo(listOf("item"))
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun registeringTheSameKeysTwiceIsNotAllowed() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key") { 100L }
+        registry.registerProvider("key") { 100L }
+    }
+
+    @Test
+    fun nullValuesAreNotSaved() {
+        val registry = createRegistry()
+
+        registry.registerProvider("key") { null }
+
+        registry.performSave().apply {
+            assertThat(containsKey("key")).isFalse()
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun emptyKeysAreNotAllowed() {
+        val registry = createRegistry()
+
+        registry.registerProvider("") { null }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun blankKeysAreNotAllowed() {
+        val registry = createRegistry()
+
+        registry.registerProvider("     ") { null }
+    }
+
+    @Test
+    fun restoreSimpleValues() {
+        val restored = mapOf("key1" to "value", "key2" to 2f)
+        val registry = createRegistry(restored)
+
+        assertThat(registry.consumeRestored("key1")).isEqualTo("value")
+        assertThat(registry.consumeRestored("key2")).isEqualTo(2f)
+    }
+
+    @Test
+    fun restoreClearsTheStoredValue() {
+        val restored = mapOf("key" to "value")
+        val registry = createRegistry(restored)
+
+        assertThat(registry.consumeRestored("key")).isEqualTo("value")
+        assertThat(registry.consumeRestored("key")).isNull()
+    }
+
+    @Test
+    fun unusedRestoredValueSavedAgain() {
+        val restored = mapOf("key1" to "value")
+        val registry = createRegistry(restored)
+
+        registry.registerProvider("key2") { 1 }
+
+        registry.performSave().apply {
+            assertThat(get("key1")).isEqualTo("value")
+            assertThat(get("key2")).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun canBeSavedIsCallingOurCallback() {
+        var canBeSavedCalled = false
+        val registry = createRegistry {
+            canBeSavedCalled = true
+            it is String
+        }
+
+        assertThat(registry.canBeSaved(1)).isFalse()
+        assertThat(canBeSavedCalled).isTrue()
+
+        canBeSavedCalled = false
+        assertThat(registry.canBeSaved("test")).isTrue()
+        assertThat(canBeSavedCalled).isTrue()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun valueWhichCantBeSavedIsNotAllowed() {
+        val registry = createRegistry { false }
+
+        registry.registerProvider("key") { 1 }
+
+        registry.performSave()
+    }
+
+    private fun createRegistry(
+        restored: Map<String, Any>? = null,
+        canBeSaved: (Any) -> Boolean = { true }
+    ) = UiSavedStateRegistry(restored, canBeSaved)
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
index f2d03fe..352eaef 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
@@ -19,8 +19,7 @@
 import androidx.test.filters.MediumTest
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.onPositioned
 import androidx.ui.layout.Column
 import androidx.ui.layout.Container
 import androidx.ui.layout.LayoutGravity
@@ -51,17 +50,16 @@
         var parentCoordinates: LayoutCoordinates? = null
         var childCoordinates: LayoutCoordinates? = null
         composeTestRule.setContent {
-            Column {
-                OnPositioned { coordinates ->
-                    parentCoordinates = coordinates
-                    latch.countDown()
-                }
-                OnChildPositioned( coordinates ->
-                    childCoordinates = coordinates
-                    latch.countDown()
-                }) {
-                    Container(width = 10.dp, height = 10.dp, modifier = LayoutGravity.Start) {}
-                }
+            Column(onPositioned { coordinates ->
+                parentCoordinates = coordinates
+                latch.countDown()
+            }) {
+                Container(width = 10.dp, height = 10.dp, modifier = LayoutGravity.Start +
+                        onPositioned { coordinates ->
+                            childCoordinates = coordinates
+                            latch.countDown()
+                        }
+                ) {}
             }
         }
 
@@ -78,21 +76,20 @@
         composeTestRule.setContent {
             with(DensityAmbient.current) {
                 Container(LayoutWidth(40.ipx.toDp())) {
-                    Column(LayoutWidth(20.ipx.toDp())) {
-                        OnPositioned { coordinates ->
-                            parentCoordinates = coordinates
-                            latch.countDown()
-                        }
-                        OnChildPositioned( coordinates ->
-                            childCoordinates = coordinates
-                            latch.countDown()
-                        }) {
-                            Container(
-                                width = 10.ipx.toDp(),
-                                height = 10.ipx.toDp(),
-                                modifier = LayoutGravity.Center
-                            ) {}
-                        }
+                    Column(LayoutWidth(20.ipx.toDp()) +
+                    onPositioned { coordinates ->
+                        parentCoordinates = coordinates
+                        latch.countDown()
+                    }) {
+                        Container(
+                            width = 10.ipx.toDp(),
+                            height = 10.ipx.toDp(),
+                            modifier = LayoutGravity.Center +
+                                    onPositioned { coordinates ->
+                                        childCoordinates = coordinates
+                                        latch.countDown()
+                                    }
+                        ) {}
                     }
                 }
             }
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt b/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
index f9600d6..272a3f2 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
@@ -20,7 +20,7 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
-import androidx.ui.core.OnChildPositioned
+import androidx.ui.core.onChildPositioned
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.dp
 import androidx.ui.layout.DpConstraints
@@ -55,12 +55,10 @@
         Stack {
             Stack(
                 LayoutSize.Min(parentConstraints.minWidth, parentConstraints.minHeight) +
-                        LayoutSize.Max(parentConstraints.maxWidth, parentConstraints.maxHeight)
+                        LayoutSize.Max(parentConstraints.maxWidth, parentConstraints.maxHeight) +
+                        onChildPositioned { coordinates -> realSize = coordinates.size.toPxSize() }
             ) {
-                OnChildPositioned(
-                     coordinates -> realSize = coordinates.size.toPxSize() },
-                    children = children
-                )
+                    children()
             }
         }
     }
diff --git a/ui/ui-text/api/0.1.0-dev06.txt b/ui/ui-text/api/0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/0.1.0-dev06.txt
+++ b/ui/ui-text/api/0.1.0-dev06.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/0.1.0-dev07.txt b/ui/ui-text/api/0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/0.1.0-dev07.txt
+++ b/ui/ui-text/api/0.1.0-dev07.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/api/restricted_0.1.0-dev06.txt b/ui/ui-text/api/restricted_0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev06.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev06.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/restricted_0.1.0-dev07.txt b/ui/ui-text/api/restricted_0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev07.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -119,6 +119,7 @@
   }
 
   public interface PlatformTextInputService {
+    method public void hideSoftwareKeyboard();
     method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
 
   public class TextInputService {
     ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+    method public void hideSoftwareKeyboard(int token);
     method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.ui.input.InputState model);
     method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
   }
 
   public static final class TextStyle.Companion {
-    method public androidx.ui.text.TextStyle getEmpty();
-    property public final androidx.ui.text.TextStyle Empty;
+    method public androidx.ui.text.TextStyle getDefault();
+    property public final androidx.ui.text.TextStyle Default;
   }
 
   public final class TextStyleKt {
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
index f9b7e4a..f0b351a 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
@@ -1628,6 +1628,40 @@
         }
     }
 
+    @Test
+    fun lineCount_withMaxLineSmallerThanTextLines() {
+        with(defaultDensity) {
+            val text = "a\na\na"
+            val fontSize = 100.sp
+            val lineCount = text.lines().size
+            val maxLines = lineCount - 1
+            val paragraph = simpleParagraph(
+                text = text,
+                style = TextStyle(fontSize = fontSize),
+                maxLines = maxLines
+            )
+
+            assertThat(paragraph.lineCount).isEqualTo(maxLines)
+        }
+    }
+
+    @Test
+    fun lineCount_withMaxLineGreaterThanTextLines() {
+        with(defaultDensity) {
+            val text = "a\na\na"
+            val fontSize = 100.sp
+            val lineCount = text.lines().size
+            val maxLines = lineCount + 1
+            val paragraph = simpleParagraph(
+                text = text,
+                style = TextStyle(fontSize = fontSize),
+                maxLines = maxLines
+            )
+
+            assertThat(paragraph.lineCount).isEqualTo(lineCount)
+        }
+    }
+
     @Test(expected = java.lang.IllegalArgumentException::class)
     fun maxLines_withMaxLineEqualsZero_throwsException() {
         simpleParagraph(
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
index b3815a3..e7ec69c 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
@@ -54,7 +54,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -75,7 +75,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -99,7 +99,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -161,7 +161,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -216,7 +216,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -281,7 +281,7 @@
             val selectionColor = Color(0x66AABB33)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -323,7 +323,7 @@
     fun multiParagraphIntrinsics_isReused() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = "abc"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -353,7 +353,7 @@
     fun TextLayoutInput_reLayout_withDifferentHeight() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = "Hello World!"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -375,7 +375,7 @@
     fun TextLayoutResult_reLayout_withDifferentHeight() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = "Hello World!"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
index 409f75a..628b44e 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
@@ -52,7 +52,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -74,7 +74,7 @@
         val annotatedString = AnnotatedString(text, spanStyle)
         val textDelegate = TextDelegate(
             text = annotatedString,
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -94,7 +94,7 @@
             val annotatedString = AnnotatedString(text, spanStyle)
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -110,7 +110,7 @@
     fun layout_build_layoutResult() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = "Hello"),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -131,7 +131,7 @@
 
         val textDelegate = TextDelegate(
             text = annotatedString,
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -157,7 +157,7 @@
 
             val textDelegate = TextDelegate(
                 text = annotatedString,
-                style = TextStyle.Empty,
+                style = TextStyle.Default,
                 density = this,
                 resourceLoader = resourceLoader,
                 layoutDirection = LayoutDirection.Ltr
@@ -179,7 +179,7 @@
         val annotatedString = AnnotatedString(text, spanStyle)
         val textDelegate = TextDelegate(
             text = annotatedString,
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
diff --git a/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt b/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
index e626d2e..f3ee0ac 100644
--- a/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
@@ -89,6 +89,13 @@
         platformTextInputService.showSoftwareKeyboard()
     }
 
+    /**
+     * Hide onscreen keyboard
+     */
+    open fun hideSoftwareKeyboard(token: InputSessionToken) = ignoreIfExpired(token) {
+        platformTextInputService.hideSoftwareKeyboard()
+    }
+
     /*
      * Notify the new editor model to IME.
      */
@@ -131,6 +138,11 @@
      */
     fun showSoftwareKeyboard()
 
+    /**
+     * Hide software keyboard
+     */
+    fun hideSoftwareKeyboard()
+
     /*
      * Notify the new editor model to IME.
      */
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt b/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
index c1a1f3b..e2a8406 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
@@ -160,7 +160,7 @@
      * If the given text style is null, returns this text style.
      */
     fun merge(other: TextStyle? = null): TextStyle {
-        if (other == null) return this
+        if (other == null || other == Default) return this
         return TextStyle(
             spanStyle = toSpanStyle().merge(other.toSpanStyle()),
             paragraphStyle = toParagraphStyle().merge(other.toParagraphStyle())
@@ -183,9 +183,9 @@
 
     companion object {
         /**
-         * Constant for no text style.
+         * Constant for default text style.
          */
-        val Empty = TextStyle()
+        val Default = TextStyle()
     }
 }
 
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
index 498c302..a09c425 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
@@ -120,14 +120,7 @@
     }
 
     override val height: Float
-        get() = layout.let {
-            val lineCount = it.lineCount
-            if (maxLines < lineCount) {
-                it.getLineBottom(maxLines - 1)
-            } else {
-                it.height.toFloat()
-            }
-        }
+        get() = layout.height.toFloat()
 
     override val maxIntrinsicWidth: Float
         get() = paragraphIntrinsics.maxIntrinsicWidth
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
index 6531ca1..d1b7b81 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
@@ -36,7 +36,7 @@
     fun `constructor with default values`() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = ""),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -51,7 +51,7 @@
         val text = AnnotatedString("Hello")
         val textDelegate = TextDelegate(
             text = text,
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr
@@ -66,7 +66,7 @@
 
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = ""),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             maxLines = maxLines,
             density = density,
             resourceLoader = resourceLoader,
@@ -82,7 +82,7 @@
 
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = ""),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             overflow = overflow,
             density = density,
             resourceLoader = resourceLoader,
@@ -96,7 +96,7 @@
     fun `minIntrinsicWidth without layout assertion should fail`() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = ""),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr)
@@ -108,7 +108,7 @@
     fun `maxIntrinsicWidth without layout assertion should fail`() {
         val textDelegate = TextDelegate(
             text = AnnotatedString(text = ""),
-            style = TextStyle.Empty,
+            style = TextStyle.Default,
             density = density,
             resourceLoader = resourceLoader,
             layoutDirection = LayoutDirection.Ltr)
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
index 36ab1f4..7f6b960 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
@@ -19,8 +19,10 @@
 import android.os.Handler
 import androidx.compose.Composable
 import androidx.test.rule.ActivityTestRule
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
+import androidx.ui.foundation.Box
+import androidx.ui.layout.LayoutSize
 import org.junit.Before
 import org.junit.Rule
 import java.util.concurrent.CountDownLatch
@@ -43,17 +45,12 @@
         activityTestRule.onUiThread { handler = Handler() }
     }
 
-    @Composable
-    internal fun Positioned() {
-        OnPositioned( positionedLatch.countDown() })
-    }
-
     internal fun show(composable: @Composable() () -> Unit) {
         positionedLatch = CountDownLatch(1)
         activityTestRule.onUiThread {
             activity.setContent {
-                Positioned()
-                composable()
+                Box(onPositioned { positionedLatch.countDown() } + LayoutSize.Fill,
+                    children = composable)
             }
         }
 
diff --git a/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java b/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
index 59472f5..c36bbd7 100644
--- a/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
+++ b/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
@@ -93,7 +93,7 @@
         seekBar.setMax((int) avd.getTotalDuration());
 
         start.setOnClickListener((v) -> {
-            if (!avd.isStarted()) {
+            if (!avd.isRunning()) {
                 avd.start();
             } else if (!avd.isPaused()) {
                 avd.pause();
diff --git a/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/current.txt b/vectordrawable/vectordrawable-seekable/api/current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt
diff --git a/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/restricted_current.txt b/vectordrawable/vectordrawable-seekable/api/restricted_current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/restricted_current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+  public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    method public void clearAnimationCallbacks();
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+    method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void draw(android.graphics.Canvas);
+    method @IntRange(from=0) public long getCurrentPlayTime();
+    method @Deprecated public int getOpacity();
+    method public long getTotalDuration();
+    method public boolean isPaused();
+    method public boolean isRunning();
+    method public void pause();
+    method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+    method public void resume();
+    method public void setAlpha(@IntRange(from=0, to=255) int);
+    method public void setColorFilter(android.graphics.ColorFilter?);
+    method public void setCurrentPlayTime(@IntRange(from=0) long);
+    method public void start();
+    method public void stop();
+    method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+  }
+
+  public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+    ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+    method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+    method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+  }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java b/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
index 7dcaa9d..bd117b2 100644
--- a/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
+++ b/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
@@ -302,7 +302,7 @@
         assertThat(bitmap.getPixel(0, 0)).isEqualTo(Color.RED);
 
         avd.start();
-        assertThat(avd.isStarted()).isTrue();
+        assertThat(avd.isRunning()).isTrue();
         assertThat(avd.isPaused()).isFalse();
         animationRule.advanceTimeBy(100L);
         avd.draw(canvas);
@@ -310,14 +310,14 @@
         assertThat(Color.red(pausedColor)).isLessThan(0xff);
 
         avd.pause();
-        assertThat(avd.isStarted()).isTrue();
+        assertThat(avd.isRunning()).isTrue();
         assertThat(avd.isPaused()).isTrue();
         animationRule.advanceTimeBy(1000L);
         avd.draw(canvas);
         assertThat(bitmap.getPixel(0, 0)).isEqualTo(pausedColor);
 
         avd.resume();
-        assertThat(avd.isStarted()).isTrue();
+        assertThat(avd.isRunning()).isTrue();
         assertThat(avd.isPaused()).isFalse();
         animationRule.advanceTimeBy(100L);
         avd.draw(canvas);
diff --git a/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java b/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
index 838d098..6600573 100644
--- a/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
+++ b/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
@@ -581,15 +581,21 @@
         }
     }
 
+    /**
+     * Returns whether the animation is running (has started and not yet ended).
+     *
+     * @return {@code true} if the animation is running.
+     */
     @Override
     public boolean isRunning() {
         return mAnimatedVectorState.mAnimatorSet.isRunning();
     }
 
-    public boolean isStarted() {
-        return mAnimatedVectorState.mAnimatorSet.isStarted();
-    }
-
+    /**
+     * Returns whether the animation is currently in a paused state.
+     *
+     * @return {@code true} if the animation is paused.
+     */
     public boolean isPaused() {
         return mAnimatedVectorState.mAnimatorSet.isPaused();
     }
diff --git a/webkit/integration-tests/testapp/src/main/res/values/styles.xml b/webkit/integration-tests/testapp/src/main/res/values/styles.xml
index 3bb68e4..c4c7a20 100644
--- a/webkit/integration-tests/testapp/src/main/res/values/styles.xml
+++ b/webkit/integration-tests/testapp/src/main/res/values/styles.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License.
   -->
 
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="NewApi">
     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index f6b3999..31433d2 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -744,7 +744,7 @@
      */
     // WebViewRenderProcessClient is a callback class, so it should be last. See
     // https://issuetracker.google.com/issues/139770271.
-    @SuppressLint("LambdaLast")
+    @SuppressLint({"LambdaLast", "NewApi"})
     @RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setWebViewRenderProcessClient(
@@ -784,6 +784,7 @@
      * @param webViewRenderProcessClient the {@link WebViewRenderProcessClient} to set for
      *                                   callbacks.
      */
+    @SuppressLint("NewApi")
     @RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static void setWebViewRenderProcessClient(
@@ -814,6 +815,7 @@
      * {@link #setWebViewRenderProcessClient(WebView,WebViewRenderProcessClient)} or {@code null}
      * otherwise.
      */
+    @SuppressLint("NewApi")
     @RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
     public static @Nullable WebViewRenderProcessClient getWebViewRenderProcessClient(
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
index cc64ac5..936275a 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
@@ -20,11 +20,13 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.webkit.WebViewRenderProcessClient;
 
 /**
  * Adapter class to pass a {@link android.webkit.WebViewRenderProcessClient} over to chromium.
  */
+@RequiresApi(29)
 public class WebViewRenderProcessClientFrameworkAdapter extends
             android.webkit.WebViewRenderProcessClient {
     private WebViewRenderProcessClient mWebViewRenderProcessClient;
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
index 4ce5462..b1d3040 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
@@ -16,6 +16,8 @@
 
 package androidx.webkit.internal;
 
+import android.annotation.SuppressLint;
+
 import androidx.annotation.NonNull;
 import androidx.webkit.WebViewFeature;
 import androidx.webkit.WebViewRenderProcess;
@@ -84,6 +86,7 @@
         return renderer;
     }
 
+    @SuppressLint("NewApi")
     @Override
     public boolean terminate() {
         final WebViewFeatureInternal feature =
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
index 899463c..533b154 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
@@ -55,7 +55,7 @@
     }
 
     /**
-     * Get the current posture of the foldable device.
+     * Gets the current posture of the foldable device.
      */
     @Posture
     public int getPosture() {
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
index 90b0468..eceedb1 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
@@ -64,13 +64,13 @@
         mType = type;
     }
 
-    /** Get the bounding rect of the display feature in window coordinate space. */
+    /** Gets the bounding rect of the display feature in window coordinate space. */
     @NonNull
     public Rect getBounds() {
         return mBounds;
     }
 
-    /** Get the type of the display feature. */
+    /** Gets the type of the display feature. */
     @Type
     public int getType() {
         return mType;
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
index 6b1720f..b73ee6c 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
@@ -31,38 +31,38 @@
 public interface ExtensionInterface {
 
     /**
-     * Register the support library as the callback for the extension. This interface will be used
+     * Registers the support library as the callback for the extension. This interface will be used
      * to report all extension changes to the support library.
      */
     void setExtensionCallback(@NonNull ExtensionCallback callback);
 
     /**
-     * Get current information about the display features present within the application window.
+     * Gets current information about the display features present within the application window.
      */
     @NonNull
     ExtensionWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
 
     /**
-     * Notify extension that a listener for display feature layout changes was registered for the
+     * Notifies extension that a listener for display feature layout changes was registered for the
      * given window token.
      */
     void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
 
     /**
-     * Notify extension that a listener for display feature layout changes was removed for the
+     * Notifies extension that a listener for display feature layout changes was removed for the
      * given window token.
      */
     void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
 
     /**
-     * Get current device state.
+     * Gets current device state.
      * @see #onDeviceStateListenersChanged(boolean)
      */
     @NonNull
     ExtensionDeviceState getDeviceState();
 
     /**
-     * Notify the extension that a device state change listener was updated.
+     * Notifies the extension that a device state change listener was updated.
      * @param isEmpty flag indicating if the list of device state change listeners is empty.
      */
     void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
index 46d213e..067736e 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
@@ -33,7 +33,7 @@
     private ExtensionProvider() {}
 
     /**
-     * Instantiate the Extension for the use by the WindowManager library.
+     * Instantiates the Extension for the use by the WindowManager library.
      *
      * <p>The library will instantiate the vendor implementation using this interface.
      * @return A compatible version of the {@link ExtensionInterface} for the provided library
@@ -45,7 +45,7 @@
     }
 
     /**
-     * Get the version of the vendor library on this device. If the returned version is not
+     * Gets the version of the vendor library on this device. If the returned version is not
      * supported by the WindowManager library, then some functions may not be available or
      * replaced with stub implementations.
      *
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
index 2cd77a3..fdc931d 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
@@ -42,7 +42,7 @@
     }
 
     /**
-     * Get the list of display features present within the window.
+     * Gets the list of display features present within the window.
      */
     @Nullable
     public List<ExtensionDisplayFeature> getDisplayFeatures() {
diff --git a/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
index fae4092..46a203f 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
@@ -68,7 +68,7 @@
         windowManager.unregisterLayoutChangeCallback(layoutStateChangeCallback)
     }
 
-    /** Update the device state and display feature positions. */
+    /** Updates the device state and display feature positions. */
     internal fun updateCurrentState() {
         // Cleanup previously added feature views
         val rootLayout = findViewById<FrameLayout>(R.id.featureContainerLayout)
@@ -118,7 +118,7 @@
         findViewById<TextView>(R.id.currentState).text = stateStringBuilder.toString()
     }
 
-    /** Add the current state to the text log of changes on screen. */
+    /** Adds the current state to the text log of changes on screen. */
     internal fun updateStateLog(info: Any) {
         stateLog.append(getCurrentTimeString())
             .append(" ")
diff --git a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
index 5e78b29..958d5a1 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
@@ -135,7 +135,7 @@
     }
 
     /**
-     * Update the display of the current device state.
+     * Updates the display of the current device state.
      */
     internal fun updateCurrentState(deviceState: DeviceState) {
         val stateStringBuilder = StringBuilder()
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
index 2a79691..2907a9e 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
@@ -22,7 +22,7 @@
 import androidx.window.DisplayFeature
 
 /**
- * Get the bounds of the display feature translated to the View's coordinate space and current
+ * Gets the bounds of the display feature translated to the View's coordinate space and current
  * position in the window. This will also include view padding in the calculations.
  */
 fun getFeaturePositionInViewRect(
@@ -60,7 +60,7 @@
 }
 
 /**
- * Get the layout params for placing a rectangle indicating a display feature inside a
+ * Gets the layout params for placing a rectangle indicating a display feature inside a
  * [FrameLayout].
  */
 fun getLayoutParamsForFeatureInFrameLayout(displayFeature: DisplayFeature, view: FrameLayout):
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
index c57c5bb..25b7105 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
@@ -109,7 +109,7 @@
     }
 
     /**
-     * Get the position of the split for this view.
+     * Gets the position of the split for this view.
      * @return A rect that defines of split, or {@code null} if there is no split.
      */
     private fun splitViewPositions(startView: View?, endView: View?): Array<Rect>? {
@@ -165,7 +165,7 @@
     }
 
     /**
-     * Measure a child view and see it if will fit in the provided rect.
+     * Measures a child view and sees if it will fit in the provided rect.
      * <p>Note: This method calls [View.measure] on the child view, which updates
      * its stored values for measured with and height. If the view will end up with different
      * values, it should be measured again.
diff --git a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
index a57c905..47950da 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
@@ -66,7 +66,7 @@
     }
 
     /**
-     * Unwrap the hierarchy of [ContextWrapper]-s until [Activity] is reached.
+     * Unwraps the hierarchy of [ContextWrapper]-s until [Activity] is reached.
      * @return Base [Activity] context or `null` if not available.
      */
     private fun getActivityFromContext(c: Context?): Activity? {
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
index 39dcca4..fd431c4 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
@@ -60,23 +60,23 @@
     })
     @interface Type{}
 
-    /** Get the bounding rect of the display feature in window coordinate space. */
+    /** Gets the bounding rect of the display feature in window coordinate space. */
     @NonNull
     public Rect getRect() {
         return mRect;
     }
 
-    /** Set the bounding rect of the display feature in window coordinate space. */
+    /** Sets the bounding rect of the display feature in window coordinate space. */
     public void setRect(@NonNull Rect rect) {
         mRect.set(rect);
     }
 
-    /** Get the type of the display feature. */
+    /** Gets the type of the display feature. */
     public @Type int getType() {
         return mType;
     }
 
-    /** Set the type of the display feature. */
+    /** Sets the type of the display feature. */
     public void setType(@Type int type) {
         mType = type;
     }
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
index 3b90b27..5b445da 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
@@ -29,38 +29,38 @@
 public interface SidecarInterface {
 
     /**
-     * Register the support library as the callback for the sidecar. This interface will be used to
+     * Registers the support library as the callback for the sidecar. This interface will be used to
      * report all sidecar changes to the support library.
      */
     void setSidecarCallback(@NonNull SidecarCallback callback);
 
     /**
-     * Get current information about the display features present within the application window.
+     * Gets current information about the display features present within the application window.
      */
     @NonNull
     SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
 
     /**
-     * Notify sidecar that a listener for display feature layout changes was registered for the
+     * Notifies sidecar that a listener for display feature layout changes was registered for the
      * given window token.
      */
     void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
 
     /**
-     * Notify sidecar that a listener for display feature layout changes was removed for the
+     * Notifies sidecar that a listener for display feature layout changes was removed for the
      * given window token.
      */
     void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
 
     /**
-     * Get current device state.
+     * Gets current device state.
      * @see #onDeviceStateListenersChanged(boolean)
      */
     @NonNull
     SidecarDeviceState getDeviceState();
 
     /**
-     * Notify the sidecar that a device state change listener was updated.
+     * Notifies the sidecar that a device state change listener was updated.
      * @param isEmpty flag indicating if the list of device state change listeners is empty.
      */
     void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
index 701e16c..8f41fa7a 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
@@ -32,7 +32,7 @@
     private SidecarProvider() {}
 
     /**
-     * Instantiate the Sidecar for the use by the WindowManager library.
+     * Instantiates the Sidecar for the use by the WindowManager library.
      *
      * <p>The library will instantiate the vendor implementation using this interface.
      * @return A compatible version of the {@link SidecarInterface} for the provided library
@@ -44,7 +44,7 @@
     }
 
     /**
-     * Get the version of the vendor library on this device. If the returned version is not
+     * Gets the version of the vendor library on this device. If the returned version is not
      * supported by the WindowManager library, then some functions may not be available or
      * replaced with stub implementations.
      *
diff --git a/window/window/src/androidTest/java/androidx/window/TestActivity.java b/window/window/src/androidTest/java/androidx/window/TestActivity.java
index 931acf9..ee73aac 100644
--- a/window/window/src/androidTest/java/androidx/window/TestActivity.java
+++ b/window/window/src/androidTest/java/androidx/window/TestActivity.java
@@ -64,7 +64,7 @@
     }
 
     /**
-     * Reset layout counter when waiting for a layout to happen before calling
+     * Resets layout counter when waiting for a layout to happen before calling
      * {@link #waitForLayout()}.
      */
     public void resetLayoutCounter() {
@@ -72,7 +72,7 @@
     }
 
     /**
-     * Block and wait for the next layout to happen. {@link #resetLayoutCounter()} must be called
+     * Blocks and waits for the next layout to happen. {@link #resetLayoutCounter()} must be called
      * before calling this method.
      * @return {@code true} if the layout happened before the timeout count reached zero and
      *         {@code false} if the waiting time elapsed before the layout happened.
@@ -86,7 +86,7 @@
     }
 
     /**
-     * Reset layout counter when waiting for a layout to happen before calling
+     * Resets layout counter when waiting for a layout to happen before calling
      * {@link #waitForOnResume()}.
      */
     public static void resetResumeCounter() {
diff --git a/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java b/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
index 60f2226..86e3e93 100644
--- a/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
+++ b/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
@@ -40,7 +40,7 @@
 public final class WindowBackendTest extends WindowTestBase {
 
     /**
-     * Verify that {@link WindowManager} instance would use the assigned
+     * Verifies that {@link WindowManager} instance would use the assigned
      * {@link WindowBackend}.
      */
     @Test
diff --git a/window/window/src/main/java/androidx/window/DeviceState.java b/window/window/src/main/java/androidx/window/DeviceState.java
index 1765622..b0b70a3 100644
--- a/window/window/src/main/java/androidx/window/DeviceState.java
+++ b/window/window/src/main/java/androidx/window/DeviceState.java
@@ -91,7 +91,7 @@
     }
 
     /**
-     * Get the posture of a foldable device with a flexible screen or multiple physical screens.
+     * Gets the posture of a foldable device with a flexible screen or multiple physical screens.
      * Devices with a single rigid display will always report {@link #POSTURE_UNKNOWN}.
      */
     @Posture
@@ -136,7 +136,7 @@
         }
 
         /**
-         * Set the posture for the {@link DeviceState} instance.
+         * Sets the posture for the {@link DeviceState} instance.
          */
         @NonNull
         public Builder setPosture(@Posture int posture) {
diff --git a/window/window/src/main/java/androidx/window/DisplayFeature.java b/window/window/src/main/java/androidx/window/DisplayFeature.java
index a7eb874..0a46eab 100644
--- a/window/window/src/main/java/androidx/window/DisplayFeature.java
+++ b/window/window/src/main/java/androidx/window/DisplayFeature.java
@@ -49,9 +49,9 @@
     }
 
     /**
-     * Get bounding rectangle of the physical display feature in the coordinate space of the window.
-     * The rectangle provides information about the location of the feature in the window and its
-     * size.
+     * Gets bounding rectangle of the physical display feature in the coordinate space of the
+     * window. The rectangle provides information about the location of the feature in the window
+     * and its size.
      */
     @NonNull
     public Rect getBounds() {
@@ -59,7 +59,7 @@
     }
 
     /**
-     * Get type of the physical display feature.
+     * Gets type of the physical display feature.
      */
     @Type
     public int getType() {
@@ -115,7 +115,7 @@
         }
 
         /**
-         * Set the bounds for the {@link DisplayFeature} instance.
+         * Sets the bounds for the {@link DisplayFeature} instance.
          */
         @NonNull
         public Builder setBounds(@NonNull Rect bounds) {
@@ -124,7 +124,7 @@
         }
 
         /**
-         * Set the type for the {@link DisplayFeature} instance.
+         * Sets the type for the {@link DisplayFeature} instance.
          */
         @NonNull
         public Builder setType(@Type int type) {
diff --git a/window/window/src/main/java/androidx/window/ExtensionCompat.java b/window/window/src/main/java/androidx/window/ExtensionCompat.java
index 35d428c..87960fe 100644
--- a/window/window/src/main/java/androidx/window/ExtensionCompat.java
+++ b/window/window/src/main/java/androidx/window/ExtensionCompat.java
@@ -127,8 +127,8 @@
     }
 
     /**
-     * Convert the display feature from extension. Can return {@code null} if there is an issue with
-     * the value passed from extension.
+     * Converts the display feature from extension. Can return {@code null} if there is an issue
+     * with the value passed from extension.
      */
     @Nullable
     private static DisplayFeature displayFeatureFromExtension(ExtensionDisplayFeature feature) {
@@ -194,7 +194,7 @@
         return new DeviceState(posture);
     }
 
-    /** Verify that extension implementation corresponds to the interface of the version. */
+    /** Verifies that extension implementation corresponds to the interface of the version. */
     @Override
     @SuppressWarnings("unused")
     public boolean validateExtensionInterface() {
diff --git a/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java b/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
index 3f19eba..5b26fef 100644
--- a/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
+++ b/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
@@ -28,42 +28,42 @@
 interface ExtensionInterfaceCompat {
 
     /**
-     * Verify if the extension interface conforms to the declared version.
+     * Verifies if the extension interface conforms to the declared version.
      */
     boolean validateExtensionInterface();
 
     /**
-     * Set the callback that is used by the extension to inform about hardware state changes.
+     * Sets the callback that is used by the extension to inform about hardware state changes.
      */
     void setExtensionCallback(@NonNull ExtensionCallbackInterface extensionCallback);
 
     /**
-     * Get current information about the display features present within the application window.
+     * Gets current information about the display features present within the application window.
      */
     @NonNull
     WindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
 
     /**
-     * Notify extension that a listener for display feature layout changes was registered for the
+     * Notifies extension that a listener for display feature layout changes was registered for the
      * given window token.
      */
     void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
 
     /**
-     * Notify extension that a listener for display feature layout changes was removed for the
+     * Notifies extension that a listener for display feature layout changes was removed for the
      * given window token.
      */
     void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
 
     /**
-     * Get current device state.
+     * Gets current device state.
      * @see #onDeviceStateListenersChanged(boolean)
      */
     @NonNull
     DeviceState getDeviceState();
 
     /**
-     * Notify the extension that a device state change listener was updated.
+     * Notifies the extension that a device state change listener was updated.
      * @param isEmpty flag indicating if the list of device state change listeners is empty.
      */
     void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
index da9e589..c4098b3 100644
--- a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
+++ b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
@@ -83,7 +83,7 @@
     }
 
     /**
-     * Get the shared instance of the class.
+     * Gets the shared instance of the class.
      */
     @NonNull
     public static ExtensionWindowBackend getInstance(@NonNull Context context) {
@@ -98,7 +98,7 @@
         return sInstance;
     }
 
-    /** Try to initialize Extension, returns early if it's not available. */
+    /** Tries to initialize Extension, returns early if it's not available. */
     @SuppressLint("SyntheticAccessor")
     @GuardedBy("sLock")
     private void initExtension(Context context) {
@@ -201,7 +201,7 @@
     }
 
     /**
-     * Check if there are no more registered callbacks left for the token and inform extension if
+     * Checks if there are no more registered callbacks left for the token and inform extension if
      * needed.
      */
     @GuardedBy("sLock")
@@ -363,7 +363,7 @@
     }
 
     /**
-     * Load an instance of {@link ExtensionInterface} implemented by OEM if available on this
+     * Loads an instance of {@link ExtensionInterface} implemented by OEM if available on this
      * device. This also verifies if the loaded implementation conforms to the declared API version.
      */
     @Nullable
@@ -400,7 +400,7 @@
     }
 
     /**
-     * Check if the Extension version provided on this device is supported by the current version
+     * Checks if the Extension version provided on this device is supported by the current version
      * of the library.
      */
     @VisibleForTesting
diff --git a/window/window/src/main/java/androidx/window/SidecarCompat.java b/window/window/src/main/java/androidx/window/SidecarCompat.java
index 1f5f554..7dd9b80 100644
--- a/window/window/src/main/java/androidx/window/SidecarCompat.java
+++ b/window/window/src/main/java/androidx/window/SidecarCompat.java
@@ -212,8 +212,8 @@
     }
 
     /**
-     * Convert the display feature from extension. Can return {@code null} if there is an issue with
-     * the value passed from extension.
+     * Converts the display feature from extension. Can return {@code null} if there is an issue
+     * with the value passed from extension.
      */
     @Nullable
     private static DisplayFeature displayFeatureFromExtension(SidecarDisplayFeature feature) {
diff --git a/window/window/src/main/java/androidx/window/WindowBackend.java b/window/window/src/main/java/androidx/window/WindowBackend.java
index 7bcf861..37321f0 100644
--- a/window/window/src/main/java/androidx/window/WindowBackend.java
+++ b/window/window/src/main/java/androidx/window/WindowBackend.java
@@ -31,38 +31,38 @@
  */
 public interface WindowBackend {
     /**
-     * Get current window layout information for the provided {@link Context}. Must be called
+     * Gets current window layout information for the provided {@link Context}. Must be called
      * only after the it is attached to the window and the layout pass has happened.
      */
     @NonNull
     WindowLayoutInfo getWindowLayoutInfo(@NonNull Context context);
 
     /**
-     * Get the current device state.
+     * Gets the current device state.
      */
     @NonNull
     DeviceState getDeviceState();
 
     /**
-     * Register a callback for layout changes of the window of the current visual {@link Context}.
+     * Registers a callback for layout changes of the window of the current visual {@link Context}.
      * Must be called only after the it is attached to the window.
      */
     void registerLayoutChangeCallback(@NonNull Context context, @NonNull Executor executor,
             @NonNull Consumer<WindowLayoutInfo> callback);
 
     /**
-     * Unregister a callback for window layout changes of the {@link Context} window.
+     * Unregisters a callback for window layout changes of the {@link Context} window.
      */
     void unregisterLayoutChangeCallback(@NonNull Consumer<WindowLayoutInfo> callback);
 
     /**
-     * Register a callback for device state changes.
+     * Registers a callback for device state changes.
      */
     void registerDeviceStateChangeCallback(@NonNull Executor executor,
             @NonNull Consumer<DeviceState> callback);
 
     /**
-     * Unregister a callback for device state changes.
+     * Unregisters a callback for device state changes.
      */
     void unregisterDeviceStateChangeCallback(@NonNull Consumer<DeviceState> callback);
 }
diff --git a/window/window/src/main/java/androidx/window/WindowLayoutInfo.java b/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
index 7a812df..e926090 100644
--- a/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
+++ b/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
@@ -41,7 +41,7 @@
     }
 
     /**
-     * Get the list of physical display features within the window.
+     * Gets the list of physical display features within the window.
      */
     @NonNull
     public List<DisplayFeature> getDisplayFeatures() {
@@ -77,7 +77,7 @@
         }
 
         /**
-         * Set the display features for the {@link WindowLayoutInfo} instance.
+         * Sets the display features for the {@link WindowLayoutInfo} instance.
          */
         @NonNull
         public Builder setDisplayFeatures(@NonNull List<DisplayFeature> displayFeatures) {
diff --git a/window/window/src/main/java/androidx/window/WindowManager.java b/window/window/src/main/java/androidx/window/WindowManager.java
index c6caf69..def4990 100644
--- a/window/window/src/main/java/androidx/window/WindowManager.java
+++ b/window/window/src/main/java/androidx/window/WindowManager.java
@@ -45,7 +45,7 @@
     private WindowBackend mWindowBackend;
 
     /**
-     * Get an instance of the class initialized with and connected to the provided {@link Context}.
+     * Gets an instance of the class initialized with and connected to the provided {@link Context}.
      * All methods of this class will return information that is associated with this visual
      * context.
      * @param context A visual context, such as an {@link Activity} or a {@link ContextWrapper}
@@ -66,7 +66,7 @@
     }
 
     /**
-     * Get current window layout information for the associated {@link Context}. Must be called
+     * Gets current window layout information for the associated {@link Context}. Must be called
      * only after the it is attached to the window and the layout pass has happened.
      * @see Activity#onAttachedToWindow()
      * @see WindowLayoutInfo
@@ -77,7 +77,7 @@
     }
 
     /**
-     * Get the current device state.
+     * Gets the current device state.
      * @see DeviceState
      */
     @NonNull
@@ -86,7 +86,7 @@
     }
 
     /**
-     * Register a callback for layout changes of the window of the current visual {@link Context}.
+     * Registers a callback for layout changes of the window of the current visual {@link Context}.
      * Must be called only after the it is attached to the window.
      * @see Activity#onAttachedToWindow()
      */
@@ -96,14 +96,14 @@
     }
 
     /**
-     * Unregister a callback for window layout changes of the window.
+     * Unregisters a callback for window layout changes of the window.
      */
     public void unregisterLayoutChangeCallback(@NonNull Consumer<WindowLayoutInfo> callback) {
         mWindowBackend.unregisterLayoutChangeCallback(callback);
     }
 
     /**
-     * Register a callback for device state changes.
+     * Registers a callback for device state changes.
      */
     public void registerDeviceStateChangeCallback(@NonNull Executor executor,
             @NonNull Consumer<DeviceState> callback) {
@@ -111,14 +111,14 @@
     }
 
     /**
-     * Unregister a callback for device state changes.
+     * Unregisters a callback for device state changes.
      */
     public void unregisterDeviceStateChangeCallback(@NonNull Consumer<DeviceState> callback) {
         mWindowBackend.unregisterDeviceStateChangeCallback(callback);
     }
 
     /**
-     * Unwrap the hierarchy of {@link ContextWrapper}-s until {@link Activity} is reached.
+     * Unwraps the hierarchy of {@link ContextWrapper}-s until {@link Activity} is reached.
      * @return Base {@link Activity} context or {@code null} if not available.
      */
     @Nullable
diff --git a/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt b/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
index 88f7c8b..a4c7cf6 100644
--- a/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
+++ b/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
@@ -67,10 +67,10 @@
         if (node.valueArgumentCount >= 2) {
             val type = node.valueArguments[1].getExpressionType()?.canonicalText
             if ("long" == type) {
-                val value = node.valueArguments[1].evaluate() as Long
+                val value = node.valueArguments[1].evaluate() as? Long
                 // TimeUnit
                 val units = node.valueArguments[2].evaluate() as? Pair<ClassId, Name>
-                if (units != null) {
+                if (value != null && units != null) {
                     val (_, timeUnitType) = units
                     val interval: Long? = when (timeUnitType.identifier) {
                         "NANOSECONDS" -> TimeUnit.MINUTES.convert(value, TimeUnit.NANOSECONDS)
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
index 038fe54..3110fea 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
@@ -212,4 +212,47 @@
             .run()
             .expectClean()
     }
+
+    @Test
+    fun testWithPeriodicRequestHelper() {
+        val worker = kotlin(
+            "com/example/TestWorker.kt",
+            """
+            package com.example
+
+            import androidx.work.ListenableWorker
+
+            class TestWorker: ListenableWorker() {
+
+            }
+            """
+        ).indented().within("src")
+
+        val snippet = kotlin(
+            "com/example/Test.kt",
+            """
+            package com.example
+
+            import androidx.work.PeriodicWorkRequest
+            import com.example.TestWorker
+            import java.util.concurrent.TimeUnit
+
+            class Test {
+                fun buildPeriodicRequest(interval: Long) {
+                    val worker = TestWorker()
+                    val builder = PeriodicWorkRequest.Builder(worker, interval, TimeUnit.MINUTES)
+                }
+            }
+            """
+        ).indented().within("src")
+
+        lint().files(
+            LISTENABLE_WORKER,
+            PERIODIC_WORK_REQUEST,
+            worker,
+            snippet
+        ).issues(InvalidPeriodicWorkRequestIntervalDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
 }