Merge "Remove JvmDescriptorUtils's dependency of Types util." into androidx-master-dev
diff --git a/activity/activity-ktx/src/androidTest/java/androidx/activity/ActivityViewModelLazyTest.kt b/activity/activity-ktx/src/androidTest/java/androidx/activity/ActivityViewModelLazyTest.kt
index c774d00..ac106f6 100644
--- a/activity/activity-ktx/src/androidTest/java/androidx/activity/ActivityViewModelLazyTest.kt
+++ b/activity/activity-ktx/src/androidTest/java/androidx/activity/ActivityViewModelLazyTest.kt
@@ -21,7 +21,6 @@
 import androidx.lifecycle.ViewModelProvider
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -29,7 +28,10 @@
 
 @MediumTest
 class ActivityViewModelLazyTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @get:Rule val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
 
     @UiThreadTest
     @Test fun vmInitialization() {
diff --git a/activity/activity/build.gradle b/activity/activity/build.gradle
index 9005de6..82761ee 100644
--- a/activity/activity/build.gradle
+++ b/activity/activity/build.gradle
@@ -25,7 +25,7 @@
     api("androidx.core:core:1.1.0")
     api(project(":lifecycle:lifecycle-runtime"))
     api(project(":lifecycle:lifecycle-viewmodel"))
-    api(project(":savedstate:savedstate"))
+    api("androidx.savedstate:savedstate:1.1.0-alpha01")
     api(project(":lifecycle:lifecycle-viewmodel-savedstate"))
 
     androidTestImplementation(project(":lifecycle:lifecycle-runtime-testing"))
diff --git a/activity/activity/src/androidTest/java/androidx/activity/LeakInputMethodManagerTest.kt b/activity/activity/src/androidTest/java/androidx/activity/LeakInputMethodManagerTest.kt
index 28997f7..f324886 100644
--- a/activity/activity/src/androidTest/java/androidx/activity/LeakInputMethodManagerTest.kt
+++ b/activity/activity/src/androidTest/java/androidx/activity/LeakInputMethodManagerTest.kt
@@ -25,7 +25,6 @@
 import android.widget.TextView
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -36,8 +35,9 @@
 @RunWith(AndroidJUnit4::class)
 class LeakInputMethodManagerTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(LeakingActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(LeakingActivity::class.java)
 
     @Test
     fun leakThroughRemovedEditText() {
diff --git a/appcompat/appcompat-benchmark/src/androidTest/java/androidx/appcompat/benchmark/ViewInflationBenchmark.kt b/appcompat/appcompat-benchmark/src/androidTest/java/androidx/appcompat/benchmark/ViewInflationBenchmark.kt
index 9817973..24e689d 100644
--- a/appcompat/appcompat-benchmark/src/androidTest/java/androidx/appcompat/benchmark/ViewInflationBenchmark.kt
+++ b/appcompat/appcompat-benchmark/src/androidTest/java/androidx/appcompat/benchmark/ViewInflationBenchmark.kt
@@ -25,7 +25,6 @@
 import androidx.benchmark.junit4.measureRepeated
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -36,8 +35,9 @@
     @get:Rule
     val benchmarkRule = BenchmarkRule()
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(AppCompatActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(AppCompatActivity::class.java)
 
     @Test
     fun testTwelveKeyInflate() {
diff --git a/appcompat/appcompat/build.gradle b/appcompat/appcompat/build.gradle
index 6173edf..605a5dc 100644
--- a/appcompat/appcompat/build.gradle
+++ b/appcompat/appcompat/build.gradle
@@ -20,7 +20,7 @@
     api("androidx.drawerlayout:drawerlayout:1.0.0")
     implementation(project(":lifecycle:lifecycle-runtime"))
     implementation(project(":lifecycle:lifecycle-viewmodel"))
-    implementation(project(":savedstate:savedstate"))
+    api("androidx.savedstate:savedstate:1.1.0-alpha01")
 
     androidTestImplementation(KOTLIN_STDLIB)
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatActivityViewTreeTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatActivityViewTreeTest.kt
index 82497d0..f4c6c65 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatActivityViewTreeTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/AppCompatActivityViewTreeTest.kt
@@ -21,7 +21,6 @@
 import androidx.savedstate.ViewTreeSavedStateRegistryOwner
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -30,8 +29,9 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class AppCompatActivityViewTreeTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule<AppCompatInflaterDefaultActivity>(
+    val activityRule = androidx.test.rule.ActivityTestRule<AppCompatInflaterDefaultActivity>(
         AppCompatInflaterDefaultActivity::class.java)
 
     @Test
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeActivityTestRule.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeActivityTestRule.kt
index 4b97605..1a9d477 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeActivityTestRule.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeActivityTestRule.kt
@@ -18,13 +18,13 @@
 
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.app.AppCompatDelegate
-import androidx.test.rule.ActivityTestRule
 
+@Suppress("DEPRECATION")
 class NightModeActivityTestRule<T : AppCompatActivity>(
     activityClazz: Class<T>,
     initialTouchMode: Boolean = false,
     launchActivity: Boolean = true
-) : ActivityTestRule<T>(activityClazz, initialTouchMode, launchActivity) {
+) : androidx.test.rule.ActivityTestRule<T>(activityClazz, initialTouchMode, launchActivity) {
     override fun beforeActivityLaunched() {
         // By default we'll set the night mode to NO, which allows us to make better
         // assumptions in the test below
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
index 82f2c4f..ae0cfa0 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/testutils/NightModeUtils.kt
@@ -27,7 +27,6 @@
 import androidx.appcompat.app.AppCompatDelegate.NightMode
 import androidx.lifecycle.Lifecycle
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.LifecycleOwnerUtils
 import org.junit.Assert.assertEquals
 
@@ -67,7 +66,7 @@
     }
 
     fun <T : AppCompatActivity> setNightModeAndWait(
-        activityRule: ActivityTestRule<T>,
+        @Suppress("DEPRECATION") activityRule: androidx.test.rule.ActivityTestRule<T>,
         @NightMode nightMode: Int,
         setMode: NightSetMode
     ) {
@@ -76,7 +75,7 @@
 
     fun <T : AppCompatActivity> setNightModeAndWait(
         activity: AppCompatActivity?,
-        activityRule: ActivityTestRule<T>,
+        @Suppress("DEPRECATION") activityRule: androidx.test.rule.ActivityTestRule<T>,
         @NightMode nightMode: Int,
         setMode: NightSetMode
     ) {
@@ -92,7 +91,7 @@
     }
 
     fun <T : AppCompatActivity> setNightModeAndWaitForRecreate(
-        activityRule: ActivityTestRule<T>,
+        @Suppress("DEPRECATION") activityRule: androidx.test.rule.ActivityTestRule<T>,
         @NightMode nightMode: Int,
         setMode: NightSetMode
     ): T = setNightModeAndWaitForRecreate(activityRule.activity, nightMode, setMode)
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatAttributeTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatAttributeTest.kt
index 8ec0a32..b6ffc00 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatAttributeTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatAttributeTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
@@ -40,8 +39,13 @@
 @MediumTest
 @SdkSuppress(minSdkVersion = 29)
 class AppCompatAttributeTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(AppCompatActivity::class.java, true, false)
+    val activityRule = androidx.test.rule.ActivityTestRule(
+        AppCompatActivity::class.java,
+        true,
+        false
+    )
 
     @Before
     fun setup() {
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
index 9480999..fe65cc2 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
@@ -56,12 +56,16 @@
 import androidx.core.widget.TextViewCompat;
 
 /**
- * SwitchCompat is a version of the Switch widget which on devices back to API v7. It does not
- * make any attempt to use the platform provided widget on those devices which it is available
- * normally.
+ * SwitchCompat is a complete backport of the core {@link android.widget.Switch} widget that
+ * brings the visuals and the functionality of that widget to older versions of the platform.
+ * Unlike other widgets in this package, SwitchCompat is <strong>not</strong> automatically used
+ * in layouts that use the <code>&lt;Switch&gt;</code> element. Instead, you need to explicitly
+ * use <code>&lt;androidx.appcompat.widget.SwitchCompat&gt;</code> and the matching attributes
+ * in your layouts.
+ *
  * <p>
- * A Switch is a two-state toggle switch widget that can select between two
- * options. The user may drag the "thumb" back and forth to choose the selected option,
+ * A Switch is a two-state toggle switch widget that can be used to select one of the two
+ * available options. The user may drag the "thumb" back and forth to choose the selected option,
  * or simply tap to toggle as if it were a checkbox. The {@link #setText(CharSequence) text}
  * property controls the text displayed in the label for the switch, whereas the
  * {@link #setTextOff(CharSequence) off} and {@link #setTextOn(CharSequence) on} text
@@ -71,6 +75,12 @@
  * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and
  * the related setSwitchTypeface() methods control that of the thumb.
  *
+ * <p>
+ * The thumb can be tinted with {@link #setThumbTintList(ColorStateList)} and
+ * {@link #setThumbTintMode(PorterDuff.Mode)} APIs, as well as with the matching XML attributes.
+ * The track can be tinted with {@link #setTrackTintList(ColorStateList)} and
+ * {@link #setTrackTintMode(PorterDuff.Mode)} APIs, as well as with the matching XML attributes.
+ *
  * <p>See the <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">Toggle Buttons</a>
  * guide.</p>
  *
@@ -82,6 +92,10 @@
  * {@link android.R.attr#thumb}
  * {@link androidx.appcompat.R.attr#thumbTextPadding}
  * {@link androidx.appcompat.R.attr#track}
+ * {@link androidx.appcompat.R.attr#thumbTint}
+ * {@link androidx.appcompat.R.attr#thumbTintMode}
+ * {@link androidx.appcompat.R.attr#trackTint}
+ * {@link androidx.appcompat.R.attr#trackTintMode}
  */
 public class SwitchCompat extends CompoundButton {
     private static final int THUMB_ANIMATION_DURATION = 250;
diff --git a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionTest.java b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionTest.java
index 54471d7..7dc2fcf 100644
--- a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionTest.java
+++ b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionTest.java
@@ -57,6 +57,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Collections;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -315,6 +316,15 @@
         assertFalse(content.isValid());
     }
 
+    @Test
+    public void testContent_invalidSlice_noException() {
+        Slice slice = new Slice.Builder(Uri.parse("inline.slice"),
+                new SliceSpec("random_version", 1)).addText("title", null,
+                Collections.singletonList("RANDOM_HINT")).build();
+        InlineSuggestionUi.Content content = new InlineSuggestionUi.Content(slice);
+        assertFalse(content.isValid());
+    }
+
     /** Below are tests for the Style class */
 
     @Test
diff --git a/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java b/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
index ce709e1..f031bf4 100644
--- a/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
+++ b/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
@@ -236,7 +236,6 @@
                 return;
             }
             // start icon
-            // start icon
             if (startIconView.getVisibility() != View.GONE) {
                 ImageViewStyle startIconViewStyle = getStartIconStyle();
                 if (startIconViewStyle != null) {
@@ -474,7 +473,10 @@
         Content(@NonNull Slice slice) {
             super(slice);
             for (SliceItem sliceItem : slice.getItems()) {
-                String itemType = itemType(sliceItem);
+                final String itemType = itemType(sliceItem);
+                if (itemType == null) {
+                    continue;
+                }
                 switch (itemType) {
                     case HINT_INLINE_TITLE:
                         mTitle = sliceItem.getText().toString();
diff --git a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
index 36527f5..c1abfdf 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
@@ -17,7 +17,6 @@
 package androidx.benchmark
 
 import android.annotation.SuppressLint
-import android.app.Activity
 import android.os.Build
 import android.os.Bundle
 import android.os.Debug
@@ -537,16 +536,6 @@
         return status
     }
 
-    private fun reportResultsBundle(testName: String) {
-        val bundle = getFullStatusReport(key = testName, includeStats = !Arguments.dryRunMode)
-
-        // Before addResults() was added in the platform, we use sendStatus(). The constant '2'
-        // comes from IInstrumentationResultParser.StatusCodes.IN_PROGRESS, and signals the
-        // test infra that this is an "additional result" bundle, equivalent to addResults()
-        // NOTE: we should a version check to call addResults(), but don't yet due to b/155103514
-        InstrumentationRegistry.getInstrumentation().sendStatus(2, bundle)
-    }
-
     private fun sleepIfThermalThrottled(sleepSeconds: Long) = when {
         ThrottleDetector.isDeviceThermalThrottled() -> {
             Log.d(TAG, "THERMAL THROTTLE DETECTED, SLEEPING FOR $sleepSeconds SECONDS")
@@ -570,7 +559,9 @@
     ) {
         checkState() // this method is triggered externally
         val fullTestName = "$PREFIX$simpleClassName.$methodName"
-        reportResultsBundle(fullTestName)
+
+        val bundle = getFullStatusReport(key = fullTestName, includeStats = !Arguments.dryRunMode)
+        reportBundle(bundle)
 
         ResultWriter.appendReport(
             getReport(
@@ -600,7 +591,7 @@
             else -> 50
         }
 
-        internal const val REPEAT_COUNT_ALLOCATION = 10
+        internal const val REPEAT_COUNT_ALLOCATION = 5
 
         private val OVERRIDE_ITERATIONS = if (
             Arguments.dryRunMode ||
@@ -676,10 +667,22 @@
                 nanos = report.getStats("timeNs").min,
                 allocations = null
             )
-            InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, bundle)
+            reportBundle(bundle)
 
             // Report values to file output
             ResultWriter.appendReport(report)
         }
+
+        /**
+         * Report results bundle to instrumentation
+         *
+         * Before addResults() was added in the platform, we use sendStatus(). The constant '2'
+         * comes from IInstrumentationResultParser.StatusCodes.IN_PROGRESS, and signals the
+         * test infra that this is an "additional result" bundle, equivalent to addResults()
+         * NOTE: we should a version check to call addResults(), but don't yet due to b/155103514
+         */
+        internal fun reportBundle(
+            bundle: Bundle
+        ) = InstrumentationRegistry.getInstrumentation().sendStatus(2, bundle)
     }
 }
diff --git a/benchmark/junit4/build.gradle b/benchmark/junit4/build.gradle
index f89b39d..5952829 100644
--- a/benchmark/junit4/build.gradle
+++ b/benchmark/junit4/build.gradle
@@ -38,8 +38,8 @@
     api(JUNIT)
     api(KOTLIN_STDLIB)
 
-    implementation(ANDROIDX_TEST_RULES)
-    implementation(ANDROIDX_TEST_RUNNER)
+    implementation("androidx.test:rules:1.2.0")
+    implementation("androidx.test:runner:1.2.0")
     api("androidx.annotation:annotation:1.1.0")
 
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
index d483f61..43f50cf 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
@@ -93,8 +93,9 @@
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     int mCanceledFrom = USER_CANCELED_FROM_NONE;
 
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    boolean mStartRespectingCancel;
+    @VisibleForTesting boolean mAwaitingResult;
+
+    private boolean mConfirmingDeviceCredential;
 
     // This flag is used to control the instant dismissal of the dialog fragment. In the case where
     // the user is already locked out this dialog will not appear. In the case where the user is
@@ -111,7 +112,8 @@
     private @Nullable android.hardware.biometrics.BiometricPrompt mBiometricPrompt;
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
-    @Nullable FingerprintDialogFragment mFingerprintDialog;
+    @Nullable
+    FingerprintDialogFragment mFingerprintDialog;
 
     // Do not rely on the application's executor when calling into the framework's code.
     @SuppressWarnings("WeakerAccess") /* synthetic access */
@@ -260,9 +262,7 @@
             return;
         }
 
-        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q && isDeviceCredentialAllowed()) {
-            // Ignore the first onPause if isDeviceCredentialAllowed is true, since implementations
-            // prior to R launch ConfirmDeviceCredentialActivity, putting the client app onPause.
+        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && isDeviceCredentialAllowed()) {
             if (!mPausedOnce) {
                 mPausedOnce = true;
             } else {
@@ -277,6 +277,7 @@
     public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         if (requestCode == REQUEST_CONFIRM_CREDENTIAL) {
+            mConfirmingDeviceCredential = false;
             handleConfirmCredentialResult(resultCode);
         }
     }
@@ -313,6 +314,7 @@
                 && activity != null
                 && BiometricManager.from(activity).canAuthenticate()
                         != BiometricManager.BIOMETRIC_SUCCESS) {
+            mAwaitingResult = true;
             launchConfirmCredentialActivity();
             return;
         }
@@ -342,21 +344,27 @@
         fragmentManager.executePendingTransactions();
 
         if (!mShowing) {
+            mShowing = true;
+            mAwaitingResult = true;
             if (!isUsingFingerprintDialog()) {
                 showBiometricPromptForAuthentication();
             } else {
                 showFingerprintDialogForAuthentication();
             }
-            mShowing = true;
         }
     }
 
     void cancel(int canceledFrom) {
-        if (!isUsingFingerprintDialog()) {
-            cancelBiometricPrompt();
-        } else {
-            cancelFingerprintDialog(canceledFrom);
+        if (isUsingFingerprintDialog()) {
+            mCanceledFrom = canceledFrom;
+            if (canceledFrom == USER_CANCELED_FROM_USER) {
+                final int errorCode = BiometricPrompt.ERROR_USER_CANCELED;
+                sendErrorToClient(errorCode,
+                        Utils.getFingerprintErrorString(getContext(), errorCode));
+            }
         }
+        mCancellationSignalProvider.cancel();
+        dismiss();
     }
 
     void onNegativeButtonPressed(DialogInterface dialog, int which) {
@@ -417,9 +425,11 @@
             return;
         }
 
+        mConfirmingDeviceCredential = true;
+
         // Dismiss the fingerprint dialog before launching the activity.
         if (isUsingFingerprintDialog()) {
-            cancelFingerprintDialog(USER_CANCELED_FROM_NONE);
+            dismissFingerprintDialog();
         }
 
         // Launch a new instance of the confirm device credential Settings activity.
@@ -482,17 +492,6 @@
             builder.setDeviceCredentialAllowed(allowDeviceCredential);
         }
 
-        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q && allowDeviceCredential) {
-            mStartRespectingCancel = false;
-            mHandler.postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    // Ignore cancel signal if it's within the first quarter second.
-                    mStartRespectingCancel = true;
-                }
-            }, 250 /* ms */);
-        }
-
         mBiometricPrompt = builder.build();
         final android.os.CancellationSignal cancellationSignal =
                 mCancellationSignalProvider.getBiometricCancellationSignal();
@@ -553,44 +552,23 @@
     }
 
     /**
-     * Cancel the authentication.
-     */
-    private void cancelBiometricPrompt() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isDeviceCredentialAllowed()) {
-            if (!mStartRespectingCancel) {
-                Log.w(TAG, "Ignoring fast cancel signal");
-                return;
-            }
-        }
-        mCancellationSignalProvider.cancel();
-        dismiss();
-    }
-
-    private void cancelFingerprintDialog(int canceledFrom) {
-        mCanceledFrom = canceledFrom;
-        if (canceledFrom == USER_CANCELED_FROM_USER) {
-            final int errorCode = BiometricPrompt.ERROR_USER_CANCELED;
-            sendErrorToClient(errorCode, Utils.getFingerprintErrorString(getContext(), errorCode));
-        }
-        mCancellationSignalProvider.cancel();
-        dismiss();
-    }
-
-    /**
      * Remove the fragment so that resources can be freed.
      */
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     void dismiss() {
+        mShowing = false;
+        dismissFingerprintDialog();
+        if (isAdded()) {
+            getParentFragmentManager().beginTransaction().detach(this).commitAllowingStateLoss();
+        }
+    }
+
+    private void dismissFingerprintDialog() {
         if (mFingerprintDialog != null) {
             mFingerprintDialog.dismissSafely();
             mFingerprintDialog = null;
         }
 
-        mShowing = false;
-        if (isAdded()) {
-            getParentFragmentManager().beginTransaction().detach(this).commitAllowingStateLoss();
-        }
-
         FragmentManager fragmentManager = getClientFragmentManager();
         if (fragmentManager != null) {
             final Fragment fingerprintFragment = fragmentManager.findFragmentByTag(
@@ -615,7 +593,13 @@
     }
 
     private void sendSuccessToClient(@NonNull final BiometricPrompt.AuthenticationResult result) {
+        if (!mAwaitingResult) {
+            Log.w(TAG, "Success not sent to client. Client is not awaiting a result.");
+            return;
+        }
+
         if (mClientExecutor != null && mClientCallback != null) {
+            mAwaitingResult = false;
             mClientExecutor.execute(
                     new Runnable() {
                         @Override
@@ -630,7 +614,18 @@
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     void sendErrorToClient(final int errorCode, @NonNull final CharSequence errorString) {
+        if (mConfirmingDeviceCredential) {
+            Log.v(TAG, "Error not sent to client. User is confirming their device credential.");
+            return;
+        }
+
+        if (!mAwaitingResult) {
+            Log.w(TAG, "Error not sent to client. Client is not awaiting a result.");
+            return;
+        }
+
         if (mClientExecutor != null && mClientCallback != null) {
+            mAwaitingResult = false;
             mClientExecutor.execute(new Runnable() {
                 @Override
                 public void run() {
@@ -644,6 +639,11 @@
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     void sendFailureToClient() {
+        if (!mAwaitingResult) {
+            Log.w(TAG, "Failure not sent to client. Client is not awaiting a result.");
+            return;
+        }
+
         if (mClientExecutor != null && mClientCallback != null) {
             mClientExecutor.execute(new Runnable() {
                 @Override
diff --git a/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java b/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
index e16af31..0eedc52 100644
--- a/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
+++ b/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
@@ -21,7 +21,7 @@
 import static org.mockito.Mockito.verify;
 
 import androidx.annotation.NonNull;
-import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,7 +35,7 @@
 
 import java.util.concurrent.Executor;
 
-@LargeTest
+@MediumTest
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
 public class BiometricFragmentTest {
@@ -68,7 +68,7 @@
     @Test
     public void testOnBiometricSucceeded_TriggersCallbackWithNullCrypto_WhenGivenNullResult() {
         mFragment.setClientCallback(EXECUTOR, mAuthenticationCallback);
-
+        mFragment.mAwaitingResult = true;
         mFragment.mCallbackProvider.getBiometricCallback()
                 .onAuthenticationSucceeded(null /* result */);
 
@@ -79,7 +79,7 @@
     @Test
     public void testOnFingerprintSucceeded_TriggersCallbackWithNullCrypto_WhenGivenNullResult() {
         mFragment.setClientCallback(EXECUTOR, mAuthenticationCallback);
-
+        mFragment.mAwaitingResult = true;
         mFragment.mCallbackProvider.getFingerprintCallback()
                 .onAuthenticationSucceeded(null /* result */);
 
@@ -89,10 +89,11 @@
 
     @Test
     public void testOnFingerprintError_DoesShowErrorAndDismissDialog_WhenHardwareUnavailable() {
-        mFragment.setClientCallback(EXECUTOR, mAuthenticationCallback);
-
         final int errMsgId = BiometricConstants.ERROR_HW_UNAVAILABLE;
         final String errString = "lorem ipsum";
+
+        mFragment.setClientCallback(EXECUTOR, mAuthenticationCallback);
+        mFragment.mAwaitingResult = true;
         mFragment.mCallbackProvider.getFingerprintCallback()
                 .onAuthenticationError(errMsgId, errString);
 
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 4561ed1..b898202 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -39,7 +39,12 @@
     tasks.withType(KotlinCompile).configureEach {
         kotlinOptions {
             jvmTarget = "1.8"
-            freeCompilerArgs += ["-Werror", "-Xskip-runtime-version-check"]
+            freeCompilerArgs += [
+                    "-Werror",
+                    "-Xskip-runtime-version-check",
+                    // Allow `@OptIn` and `@UseExperimental`
+                    "-Xopt-in=kotlin.RequiresOptIn"
+            ]
         }
     }
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
index eaca4ff..8e8908d 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
@@ -18,20 +18,12 @@
 
 import androidx.benchmark.gradle.BenchmarkPlugin
 import androidx.build.AndroidXPlugin.Companion.CHECK_RELEASE_READY_TASK
-import androidx.build.AndroidXPlugin.Companion.CHECK_RESOURCE_API_TASK
 import androidx.build.AndroidXPlugin.Companion.TASK_TIMEOUT_MINUTES
-import androidx.build.AndroidXPlugin.Companion.UPDATE_RESOURCE_API_TASK
 import androidx.build.SupportConfig.BUILD_TOOLS_VERSION
 import androidx.build.SupportConfig.COMPILE_SDK_VERSION
 import androidx.build.SupportConfig.DEFAULT_MIN_SDK_VERSION
 import androidx.build.SupportConfig.INSTRUMENTATION_RUNNER
 import androidx.build.SupportConfig.TARGET_SDK_VERSION
-import androidx.build.checkapi.ApiType
-import androidx.build.checkapi.getApiFileDirectory
-import androidx.build.checkapi.getCurrentApiLocation
-import androidx.build.checkapi.getRequiredCompatibilityApiFileFromDir
-import androidx.build.checkapi.getVersionedApiLocation
-import androidx.build.checkapi.hasApiFileDirectory
 import androidx.build.dependencyTracker.AffectedModuleDetector
 import androidx.build.dokka.Dokka.configureAndroidProjectForDokka
 import androidx.build.dokka.Dokka.configureJavaProjectForDokka
@@ -41,9 +33,8 @@
 import androidx.build.license.configureExternalDependencyLicenseCheck
 import androidx.build.metalava.MetalavaTasks.configureAndroidProjectForMetalava
 import androidx.build.metalava.MetalavaTasks.configureJavaProjectForMetalava
-import androidx.build.metalava.UpdateApiTask
+import androidx.build.resources.ResourceTasks.configureAndroidProjectForResourceTasks
 import androidx.build.studio.StudioTask
-import androidx.build.uptodatedness.cacheEvenIfNoOutputs
 import com.android.build.gradle.AppExtension
 import com.android.build.gradle.AppPlugin
 import com.android.build.gradle.LibraryExtension
@@ -218,7 +209,6 @@
 
         project.configureSourceJarForAndroid(libraryExtension)
         project.configureVersionFileWriter(libraryExtension, androidXExtension)
-        project.configureResourceApiChecks(libraryExtension)
         project.addCreateLibraryBuildInfoFileTask(androidXExtension)
 
         val verifyDependencyVersionsTask = project.createVerifyDependencyVersionsTask()
@@ -249,12 +239,13 @@
             }
         }
 
-        // Standard lint, docs, and Metalava configuration for AndroidX projects.
+        // Standard lint, docs, resource API, and Metalava configuration for AndroidX projects.
         project.configureAndroidProjectForLint(libraryExtension.lintOptions, androidXExtension)
         if (project.isDocumentationEnabled()) {
             project.configureAndroidProjectForDokka(libraryExtension, androidXExtension)
         }
         project.configureAndroidProjectForMetalava(libraryExtension, androidXExtension)
+        project.configureAndroidProjectForResourceTasks(libraryExtension, androidXExtension)
 
         project.addToProjectMap(androidXExtension)
     }
@@ -604,12 +595,15 @@
         const val BUILD_ON_SERVER_TASK = "buildOnServer"
         const val BUILD_TEST_APKS_TASK = "buildTestApks"
         const val CHECK_RESOURCE_API_TASK = "checkResourceApi"
+        const val CHECK_RESOURCE_API_RELEASE_TASK = "checkResourceApiRelease"
         const val UPDATE_RESOURCE_API_TASK = "updateResourceApi"
         const val CHECK_RELEASE_READY_TASK = "checkReleaseReady"
         const val CREATE_LIBRARY_BUILD_INFO_FILES_TASK = "createLibraryBuildInfoFiles"
         const val CREATE_AGGREGATE_BUILD_INFO_FILES_TASK = "createAggregateBuildInfoFiles"
         const val REPORT_LIBRARY_METRICS_TASK = "reportLibraryMetrics"
 
+        const val TASK_GROUP_API = "API"
+
         const val EXTENSION_NAME = "androidx"
 
         /**
@@ -660,18 +654,6 @@
     get() = extensions.findByType(KotlinMultiplatformExtension::class.java)
 
 /**
- * Creates the [CHECK_RESOURCE_API_TASK], which verifies the AAPT-generated resource API file
- * against the checked-in resource API file.
- */
-private fun Project.createCheckResourceApiTask(): TaskProvider<CheckResourceApiTask> {
-    return tasks.register(CHECK_RESOURCE_API_TASK, CheckResourceApiTask::class.java) { task ->
-        task.newApiFile = getGeneratedResourceApiFile()
-        task.oldApiFile = getVersionedApiLocation().resourceFile
-        task.cacheEvenIfNoOutputs()
-    }
-}
-
-/**
  * Creates the [CHECK_RELEASE_READY_TASK], which aggregates tasks that must pass for a
  * project to be considered ready for public release.
  */
@@ -683,69 +665,12 @@
     }
 }
 
-private fun Project.createUpdateResourceApiTask(): TaskProvider<UpdateResourceApiTask> {
-    val versionedApiLocation = project.getVersionedApiLocation()
-    val currentApiLocation = project.getCurrentApiLocation()
-
-    val outputApiLocations = if (project.isVersionedApiFileWritingEnabled()) {
-        listOf(
-            versionedApiLocation,
-            currentApiLocation
-        )
-    } else {
-        listOf(
-            currentApiLocation
-        )
-    }
-
-    return tasks.register(UPDATE_RESOURCE_API_TASK, UpdateResourceApiTask::class.java) { task ->
-        task.inputApiFile.set(getGeneratedResourceApiFile())
-        task.referenceResourceApiFile.set(getRequiredCompatibilityApiFileFromDir(
-            getApiFileDirectory(), version(), ApiType.RESOURCEAPI))
-        task.outputApiLocations.set(outputApiLocations)
-    }
-}
-
-private fun Project.getGeneratedResourceApiFile(): File {
-    // TODO(alanv): Follow up when b/154626581 gets resolved and AGP provides a stable API contract
-    return File(buildDir, "intermediates/public_res/release/public.txt")
-}
-
 @Suppress("UNCHECKED_CAST")
 fun Project.getProjectsMap(): ConcurrentHashMap<String, String> {
     return rootProject.extra.get("projects") as ConcurrentHashMap<String, String>
 }
 
 /**
- * Configures an Android library project to track and validate its public resource API surface.
- */
-private fun Project.configureResourceApiChecks(extension: LibraryExtension) {
-    // TODO(alanv): Fix this to occur during normal configuration.
-    afterEvaluate { project ->
-        // Only configure resource API checks for projects that are already tracking APIs.
-        // TODO(alanv): Migrate to check the AndroidX extension for "should generate API files".
-        if (project.hasApiFileDirectory()) {
-            val checkResourceApiTask = createCheckResourceApiTask()
-            val updateResourceApiTask = createUpdateResourceApiTask()
-
-            // Configure the check- and update- resource API tasks to depend on Java compilation,
-            // after which we expect the AAPT-generated public.txt file to be available.
-            extension.defaultPublishVariant { libraryVariant ->
-                // TODO(alanv): These should probably depend on public.txt as an input file.
-                checkResourceApiTask.configure { it.dependsOn(libraryVariant.javaCompileProvider) }
-                updateResourceApiTask.configure { it.dependsOn(libraryVariant.javaCompileProvider) }
-            }
-
-            // Ensure that this task runs as part of updateApi and buildOnServer
-            tasks.withType(UpdateApiTask::class.java).configureEach { task ->
-                task.dependsOn(updateResourceApiTask)
-            }
-            addToBuildOnServer(checkResourceApiTask)
-        }
-    }
-}
-
-/**
  * Configures all non-Studio tasks in a project (see b/153193718 for background) to time out after
  * [TASK_TIMEOUT_MINUTES].
  */
diff --git a/buildSrc/src/main/kotlin/androidx/build/CheckResourceApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/CheckResourceApiTask.kt
deleted file mode 100644
index 0670395..0000000
--- a/buildSrc/src/main/kotlin/androidx/build/CheckResourceApiTask.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.build
-
-import org.gradle.api.DefaultTask
-import org.gradle.api.GradleException
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.TaskAction
-import java.io.File
-
-/**
- * Task for detecting changes in the public resource surface
- */
-open class CheckResourceApiTask : DefaultTask() {
-
-    @InputFiles
-    @Optional
-    var oldApiFile: File? = null
-
-    @InputFiles
-    @Optional
-    var newApiFile: File? = null
-
-    @TaskAction
-    fun checkResourceApi() {
-        if (oldApiFile == null || !oldApiFile!!.exists()) {
-            throw GradleException("No resource api file for the current version exists, please" +
-                    " run updateApi to create one.")
-        }
-        var oldResourceApi: HashSet<String> = HashSet(oldApiFile?.readLines())
-        var newResourceApi: HashSet<String> = HashSet()
-        if (newApiFile != null && newApiFile!!.exists()) {
-            newResourceApi = HashSet(newApiFile?.readLines())
-        }
-        if (oldResourceApi != newResourceApi) {
-            throw GradleException("Public resource surface changes detected, please run" +
-                    " updateApi to confirm this change is intentional.")
-        }
-    }
-}
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
index 8c3a5ec..24180c7 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryGroups.kt
@@ -102,7 +102,7 @@
     val VERSIONEDPARCELABLE = LibraryGroup("androidx.versionedparcelable", null)
     val VIEWPAGER = LibraryGroup("androidx.viewpager", LibraryVersions.VIEWPAGER)
     val VIEWPAGER2 = LibraryGroup("androidx.viewpager2", LibraryVersions.VIEWPAGER2)
-    val WEAR = LibraryGroup("androidx.wear", LibraryVersions.WEAR)
+    val WEAR = LibraryGroup("androidx.wear", null)
     val WEBKIT = LibraryGroup("androidx.webkit", LibraryVersions.WEBKIT)
     val WINDOW = LibraryGroup("androidx.window", null)
     val WORK = LibraryGroup("androidx.work", LibraryVersions.WORK)
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index ab2b74c..116e2c0 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -72,7 +72,7 @@
     val LEANBACK_PREFERENCE = Version("1.1.0-alpha04")
     val LEGACY = Version("1.1.0-alpha01")
     val LOCALBROADCASTMANAGER = Version("1.1.0-alpha02")
-    val LIFECYCLE = Version("2.3.0-alpha03")
+    val LIFECYCLE = Version("2.3.0-alpha04")
     val LIFECYCLE_EXTENSIONS = Version("2.2.0")
     val LOADER = Version("1.2.0-alpha01")
     val MEDIA = Version("1.2.0-alpha03")
@@ -117,7 +117,8 @@
     val VIEWPAGER = Version("1.1.0-alpha01")
     val VIEWPAGER2 = Version("1.1.0-alpha02")
     val WEAR = Version("1.2.0-alpha01")
-    val WEBKIT = Version("1.3.0-beta01")
+    val WEAR_INPUT = Version("1.0.0-alpha01")
+    val WEBKIT = Version("1.3.0-rc01")
     val WINDOW = Version("1.0.0-alpha02")
     val WINDOW_SIDECAR = Version("0.1.0-alpha01")
     val WORK = Version("2.4.0-beta02")
diff --git a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
index 7659c54..fd7c65f 100644
--- a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
@@ -143,8 +143,10 @@
     prebuilts(LibraryGroups.VERSIONEDPARCELABLE, "versionedparcelable", "1.1.1")
     prebuilts(LibraryGroups.VIEWPAGER, "1.0.0")
     prebuilts(LibraryGroups.VIEWPAGER2, "1.1.0-alpha01")
-    prebuilts(LibraryGroups.WEAR, "1.1.0-rc01")
+    prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc01")
             .addStubs("wear/wear_stubs/com.google.android.wearable-stubs.jar")
+    ignore(LibraryGroups.WEAR.group, "wear-input")
+    ignore(LibraryGroups.WEAR.group, "wear-input-testing")
     prebuilts(LibraryGroups.WEBKIT, "1.3.0-alpha03")
     ignore(LibraryGroups.WINDOW.group, "window-sidecar")
     prebuilts(LibraryGroups.WINDOW, "1.0.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/UpdateResourceApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/UpdateResourceApiTask.kt
deleted file mode 100644
index 36e9f41..0000000
--- a/buildSrc/src/main/kotlin/androidx/build/UpdateResourceApiTask.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-package androidx.build
-
-import androidx.build.checkapi.ApiLocation
-import org.gradle.api.DefaultTask
-import org.gradle.api.GradleException
-import org.gradle.api.provider.ListProperty
-import org.gradle.api.provider.Property
-import org.gradle.api.tasks.InputFile
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.OutputFiles
-import org.gradle.api.tasks.TaskAction
-import java.io.File
-import java.util.SortedSet
-
-/**
- * Task for updating the public resource surface
- */
-abstract class UpdateResourceApiTask : DefaultTask() {
-    /** Optional text file from which the previously-released resource signatures will be read. */
-    @get:InputFile
-    @get:Optional
-    abstract val referenceResourceApiFile: Property<File>
-
-    /**
-     * Text file from which resource signatures will be read. A file path must be specified at
-     * configuration time even if the file may not exist at build time.
-     */
-    @get:Internal
-    abstract val inputApiFile: Property<File>
-
-    @InputFile
-    @Optional
-    fun getInputApiFileIfExists(): File? {
-        val file = inputApiFile.get()
-        return if (file.exists()) {
-            file
-        } else {
-            null
-        }
-    }
-
-    /** Text files to which resource signatures will be written. */
-    @get:Internal
-    abstract val outputApiLocations: ListProperty<ApiLocation>
-
-    @OutputFiles
-    fun getTaskOutputs(): List<File> {
-        return outputApiLocations.get().flatMap { outputApiLocation ->
-            listOf(
-                outputApiLocation.resourceFile
-            )
-        }
-    }
-
-    @TaskAction
-    fun verifyAndUpdateResourceApi() {
-        val newApiFile = inputApiFile.get()
-        val referenceApiFile = referenceResourceApiFile.orNull
-
-        // Read the current API surface, if any, into memory.
-        val newApiSet = if (newApiFile.exists()) {
-            HashSet(newApiFile.readLines())
-        } else {
-            emptySet<String>()
-        }
-
-        // If a reference API file was specified, verify the current API surface.
-        if (referenceApiFile != null && referenceApiFile.exists()) {
-            // Read the reference API surface into memory.
-            val oldVersion = Version(
-                referenceApiFile.name.removePrefix("res-").removeSuffix(".txt")
-            )
-            val oldApiSet: HashSet<String> = HashSet(referenceApiFile.readLines())
-            checkApiCompatibility(oldVersion, oldApiSet, project.version(), newApiSet)
-        }
-
-        // Sort the resources for the sake of source control diffs.
-        val newApiSortedSet: SortedSet<String> = newApiSet.toSortedSet()
-
-        // Write current API surface to output locations.
-        for (outputApiLocation in outputApiLocations.get()) {
-            val outputApiFile = outputApiLocation.resourceFile
-            outputApiFile.bufferedWriter().use { out ->
-                newApiSortedSet.forEach {
-                    out.write(it)
-                    out.newLine()
-                }
-            }
-        }
-    }
-
-    private fun checkApiCompatibility(
-        referenceVersion: Version,
-        referenceApiSet: Set<String>,
-        newVersion: Version,
-        newApiSet: Set<String>
-    ) {
-        // Compute the diff.
-        val removedApi = HashSet<String>()
-        val addedApi = HashSet<String>(newApiSet)
-        for (e in referenceApiSet) {
-            if (newApiSet.contains(e)) {
-                addedApi.remove(e)
-            } else {
-                removedApi.add(e)
-            }
-        }
-
-        // POLICY: Ensure that no resources are removed within the span of a major version.
-        if (referenceVersion.major == newVersion.major && removedApi.isNotEmpty()) {
-            var errorMessage = "Cannot remove public resources within the same major version, " +
-                    "the following were removed since version $referenceVersion:\n"
-            for (e in removedApi) {
-                errorMessage += "$e\n"
-            }
-            throw GradleException(errorMessage)
-        }
-
-        // POLICY: Ensure that no resources are added to a finalized version.
-        if (newVersion.isFinalApi() && addedApi.isNotEmpty()) {
-            var errorMessage = "Cannot add public resources when api becomes final, " +
-                    "the following resources were added since version $referenceVersion:\n"
-            for (e in addedApi) {
-                errorMessage += "$e\n"
-            }
-            throw GradleException(errorMessage)
-        }
-    }
-}
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 3422c41..9fa289b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -16,13 +16,13 @@
 
 package androidx.build.dependencies
 
-const val ANDROIDX_TEST_CORE = "androidx.test:core:1.2.0"
-const val ANDROIDX_TEST_EXT_JUNIT = "androidx.test.ext:junit:1.1.1"
-const val ANDROIDX_TEST_EXT_KTX = "androidx.test.ext:junit-ktx:1.1.1"
-const val ANDROIDX_TEST_EXT_TRUTH = "androidx.test.ext:truth:1.3.0-alpha03"
-const val ANDROIDX_TEST_MONITOR = "androidx.test:monitor:1.2.0"
-const val ANDROIDX_TEST_RULES = "androidx.test:rules:1.2.0"
-const val ANDROIDX_TEST_RUNNER = "androidx.test:runner:1.2.0"
+const val ANDROIDX_TEST_CORE = "androidx.test:core:1.3.0-rc01"
+const val ANDROIDX_TEST_EXT_JUNIT = "androidx.test.ext:junit:1.1.2-rc01"
+const val ANDROIDX_TEST_EXT_KTX = "androidx.test.ext:junit-ktx:1.1.2-rc01"
+const val ANDROIDX_TEST_EXT_TRUTH = "androidx.test.ext:truth:1.3.0-rc01"
+const val ANDROIDX_TEST_MONITOR = "androidx.test:monitor:1.3.0-rc01"
+const val ANDROIDX_TEST_RULES = "androidx.test:rules:1.3.0-rc01"
+const val ANDROIDX_TEST_RUNNER = "androidx.test:runner:1.3.0-rc01"
 const val ANDROIDX_TEST_UIAUTOMATOR = "androidx.test.uiautomator:uiautomator:2.2.0"
 const val AUTO_COMMON = "com.google.auto:auto-common:0.10"
 const val AUTO_SERVICE_ANNOTATIONS = "com.google.auto.service:auto-service-annotations:1.0-rc6"
@@ -38,11 +38,11 @@
 const val DAGGER = "com.google.dagger:dagger:2.28"
 const val DAGGER_COMPILER = "com.google.dagger:dagger-compiler:2.28"
 const val DEXMAKER_MOCKITO = "com.linkedin.dexmaker:dexmaker-mockito:2.25.0"
-const val ESPRESSO_CONTRIB = "androidx.test.espresso:espresso-contrib:3.2.0"
-const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.2.0"
-const val ESPRESSO_INTENTS = "androidx.test.espresso:espresso-intents:3.2.0"
-const val ESPRESSO_IDLING_RESOURCE = "androidx.test.espresso:espresso-idling-resource:3.2.0"
-const val ESPRESSO_WEB = "androidx.test.espresso:espresso-web:3.2.0"
+const val ESPRESSO_CONTRIB = "androidx.test.espresso:espresso-contrib:3.3.0-rc01"
+const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.3.0-rc01"
+const val ESPRESSO_INTENTS = "androidx.test.espresso:espresso-intents:3.3.0-rc01"
+const val ESPRESSO_IDLING_RESOURCE = "androidx.test.espresso:espresso-idling-resource:3.3.0-rc01"
+const val ESPRESSO_WEB = "androidx.test.espresso:espresso-web:3.3.0-rc01"
 const val FINDBUGS = "com.google.code.findbugs:jsr305:3.0.2"
 const val GCM_NETWORK_MANAGER = "com.google.android.gms:play-services-gcm:17.0.0"
 const val GOOGLE_COMPILE_TESTING = "com.google.testing.compile:compile-testing:0.18"
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
index 809ca0c..cdbcd3b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiEquivalenceTask.kt
@@ -62,43 +62,6 @@
         return checkedInApiFiles + builtApiFiles
     }
 
-    fun summarizeDiff(a: File, b: File): String {
-        if (!a.exists()) {
-            return "$a does not exist"
-        }
-        if (!b.exists()) {
-            return "$b does not exist"
-        }
-        val process = ProcessBuilder(listOf("diff", a.toString(), b.toString()))
-                .redirectOutput(ProcessBuilder.Redirect.PIPE)
-                .start()
-        process.waitFor()
-        var diffLines = process.inputStream.bufferedReader().readLines().toMutableList()
-        val maxSummaryLines = 50
-        if (diffLines.size > maxSummaryLines) {
-            diffLines = diffLines.subList(0, maxSummaryLines)
-            diffLines.plusAssign("[long diff was truncated]")
-        }
-        return diffLines.joinToString("\n")
-    }
-
-    private fun checkEqual(expected: File, actual: File) {
-        if (!FileUtils.contentEquals(expected, actual)) {
-            val diff = summarizeDiff(expected, actual)
-            val message = """API definition has changed
-
-                    Declared definition is $expected
-                    True     definition is $actual
-
-                    Please run `./gradlew updateApi` to confirm these changes are
-                    intentional by updating the API definition.
-
-                    Difference between these files:
-                    $diff"""
-            throw GradleException(message)
-        }
-    }
-
     @TaskAction
     fun exec() {
         val builtApiLocation = builtApi.get()
@@ -109,3 +72,40 @@
         }
     }
 }
+
+private fun summarizeDiff(a: File, b: File): String {
+    if (!a.exists()) {
+        return "$a does not exist"
+    }
+    if (!b.exists()) {
+        return "$b does not exist"
+    }
+    val process = ProcessBuilder(listOf("diff", a.toString(), b.toString()))
+        .redirectOutput(ProcessBuilder.Redirect.PIPE)
+        .start()
+    process.waitFor()
+    var diffLines = process.inputStream.bufferedReader().readLines().toMutableList()
+    val maxSummaryLines = 50
+    if (diffLines.size > maxSummaryLines) {
+        diffLines = diffLines.subList(0, maxSummaryLines)
+        diffLines.plusAssign("[long diff was truncated]")
+    }
+    return diffLines.joinToString("\n")
+}
+
+fun checkEqual(expected: File, actual: File) {
+    if (!FileUtils.contentEquals(expected, actual)) {
+        val diff = summarizeDiff(expected, actual)
+        val message = """API definition has changed
+
+                    Declared definition is $expected
+                    True     definition is $actual
+
+                    Please run `./gradlew updateApi` to confirm these changes are
+                    intentional by updating the API definition.
+
+                    Difference between these files:
+                    $diff"""
+        throw GradleException(message)
+    }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
index 6e50fd8b..e463e9a 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateApiTask.kt
@@ -99,24 +99,24 @@
             )
         }
     }
+}
 
-    fun copy(source: File, dest: File, permitOverwriting: Boolean, logger: Logger) {
-        val overwriting = (dest.exists() && source.readText() != dest.readText())
-        val changing = overwriting || !dest.exists()
-        if (changing) {
-            if (overwriting && !permitOverwriting) {
-                val message = "Modifying the API definition for a previously released artifact " +
-                        "having a final API version (version not ending in '-alpha') is not " +
-                        "allowed.\n\n" +
-                        "Previously declared definition is $dest\n" +
-                        "Current generated   definition is $source\n\n" +
-                        "Did you mean to increment the library version first?\n\n" +
-                        "If you have reason to overwrite the API files for the previous release " +
-                        "anyway, you can run `./gradlew updateApi -Pforce` to ignore this message"
-                throw GradleException(message)
-            }
-            Files.copy(source, dest)
-            logger.lifecycle("Copied $source to $dest")
+fun copy(source: File, dest: File, permitOverwriting: Boolean, logger: Logger) {
+    val overwriting = (dest.exists() && source.readText() != dest.readText())
+    val changing = overwriting || !dest.exists()
+    if (changing) {
+        if (overwriting && !permitOverwriting) {
+            val message = "Modifying the API definition for a previously released artifact " +
+                    "having a final API version (version not ending in '-alpha') is not " +
+                    "allowed.\n\n" +
+                    "Previously declared definition is $dest\n" +
+                    "Current generated   definition is $source\n\n" +
+                    "Did you mean to increment the library version first?\n\n" +
+                    "If you have reason to overwrite the API files for the previous release " +
+                    "anyway, you can run `./gradlew updateApi -Pforce` to ignore this message"
+            throw GradleException(message)
         }
+        Files.copy(source, dest)
+        logger.lifecycle("Copied $source to $dest")
     }
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiReleaseTask.kt b/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiReleaseTask.kt
new file mode 100644
index 0000000..b12b811
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiReleaseTask.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.build.resources
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.TaskAction
+import java.io.File
+
+/**
+ * Task for updating the public Android resource surface, e.g. `public.xml`.
+ */
+abstract class CheckResourceApiReleaseTask : DefaultTask() {
+    /**
+     * Text file from which the resource API signatures will be read.
+     */
+    @get:InputFile
+    abstract val referenceApiFile: Property<File>
+
+    /**
+     * Text file representing the current resource API surface to check.
+     *
+     * A file path must be specified but the file may not exist if the library has no resources.
+     */
+    @get:Internal
+    abstract val apiFile: RegularFileProperty
+
+    @InputFile
+    @Optional
+    fun getApiFileIfExists(): File? {
+        val file = apiFile.get().asFile
+        return if (file.exists()) {
+            file
+        } else {
+            null
+        }
+    }
+
+    @TaskAction
+    fun checkResourceApiRelease() {
+        val referenceApiFile = referenceApiFile.get()
+        val apiFile = apiFile.get().asFile
+
+        // Read the current API surface, if any, into memory.
+        val newApiSet = if (apiFile.exists()) {
+            apiFile.readLines().toSet()
+        } else {
+            emptySet()
+        }
+
+        // Read the reference API surface into memory.
+        val referenceApiSet = referenceApiFile.readLines().toSet()
+
+        // POLICY: Ensure that no resources are removed from the last released version.
+        val removedApiSet = referenceApiSet - newApiSet
+        if (removedApiSet.isNotEmpty()) {
+            var removed = ""
+            for (e in removedApiSet) {
+                removed += "$e\n"
+            }
+
+            val errorMessage = """Public resources have been removed since the previous revision
+
+Previous definition is ${referenceApiFile.canonicalPath}
+Current  definition is ${apiFile.canonicalPath}
+
+Public resources are considered part of the library's API surface
+and may not be removed within a major version.
+
+Removed resources:
+$removed"""
+
+            throw GradleException(errorMessage)
+        }
+    }
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiTask.kt
new file mode 100644
index 0000000..d5fd562
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/resources/CheckResourceApiTask.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.build.resources
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.TaskAction
+import java.io.File
+
+/**
+ * Task for detecting changes in the public Android resource surface, e.g. `public.xml`.
+ */
+abstract class CheckResourceApiTask : DefaultTask() {
+    /**
+     * API file (in the build dir) to check.
+     *
+     * A file path must be specified but the file may not exist if the library has no resources.
+     */
+    @get:Internal
+    abstract val builtApi: RegularFileProperty
+
+    @InputFile
+    @Optional
+    fun getBuiltApiFileIfExists(): File? {
+        val file = builtApi.get().asFile
+        return if (file.exists()) {
+            file
+        } else {
+            null
+        }
+    }
+
+    /**
+     * API files (in source control) to compare against.
+     */
+    @get:Input
+    abstract val checkedInApis: ListProperty<File>
+
+    @TaskAction
+    fun checkResourceApi() {
+        val apiFile = builtApi.get().asFile
+
+        // The built API file, if any, needs to be sorted first because that's how we store them.
+        val sortedApiLines = if (apiFile.exists()) {
+            apiFile.readLines().toSortedSet()
+        } else {
+            emptySet<String>()
+        }
+
+        val builtApiSorted = File.createTempFile("res", "txt")
+        builtApiSorted.bufferedWriter().use { out ->
+            sortedApiLines.forEach {
+                out.write(it)
+                out.newLine()
+            }
+        }
+
+        for (checkedInApi in checkedInApis.get()) {
+            androidx.build.metalava.checkEqual(checkedInApi, builtApiSorted)
+        }
+    }
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/resources/ResourceTasks.kt b/buildSrc/src/main/kotlin/androidx/build/resources/ResourceTasks.kt
new file mode 100644
index 0000000..f1dbd79
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/resources/ResourceTasks.kt
@@ -0,0 +1,152 @@
+/*
+ * 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.build.resources
+
+import androidx.build.AndroidXExtension
+import androidx.build.AndroidXPlugin.Companion.CHECK_RESOURCE_API_RELEASE_TASK
+import androidx.build.AndroidXPlugin.Companion.CHECK_RESOURCE_API_TASK
+import androidx.build.AndroidXPlugin.Companion.TASK_GROUP_API
+import androidx.build.AndroidXPlugin.Companion.UPDATE_RESOURCE_API_TASK
+import androidx.build.addToBuildOnServer
+import androidx.build.checkapi.getCurrentApiLocation
+import androidx.build.checkapi.getRequiredCompatibilityApiLocation
+import androidx.build.checkapi.getVersionedApiLocation
+import androidx.build.checkapi.hasApiFileDirectory
+import androidx.build.checkapi.hasApiTasks
+import androidx.build.defaultPublishVariant
+import androidx.build.isVersionedApiFileWritingEnabled
+import androidx.build.metalava.UpdateApiTask
+import androidx.build.uptodatedness.cacheEvenIfNoOutputs
+import com.android.build.gradle.LibraryExtension
+import org.gradle.api.Project
+import java.util.Locale
+
+object ResourceTasks {
+
+    @Suppress("UnstableApiUsage")
+    fun Project.configureAndroidProjectForResourceTasks(
+        library: LibraryExtension,
+        extension: AndroidXExtension
+    ) {
+        afterEvaluate { project ->
+            if (!hasApiTasks(this, extension)) {
+                return@afterEvaluate
+            }
+
+            library.defaultPublishVariant { variant ->
+                if (!project.hasApiFileDirectory()) {
+                    logger.info(
+                        "Project $name doesn't have an api folder, ignoring API tasks."
+                    )
+                    return@defaultPublishVariant
+                }
+
+                setupProject(project, variant.name)
+            }
+        }
+    }
+
+    private fun setupProject(
+        project: Project,
+        variantName: String
+    ) {
+        @OptIn(ExperimentalStdlibApi::class)
+        val packageResTask = project.tasks
+            .named("package${variantName.capitalize(Locale.US)}Resources")
+        val builtApiFile = packageResTask.flatMap { task ->
+            (task as com.android.build.gradle.tasks.MergeResources).publicFile
+        }
+
+        val versionedApiLocation = project.getVersionedApiLocation()
+        val currentApiLocation = project.getCurrentApiLocation()
+
+        val outputApiLocations = if (project.isVersionedApiFileWritingEnabled()) {
+            listOf(
+                versionedApiLocation,
+                currentApiLocation
+            )
+        } else {
+            listOf(
+                currentApiLocation
+            )
+        }
+
+        val outputApiFiles = outputApiLocations.map { location ->
+            location.resourceFile
+        }
+
+        // Policy: If the artifact has previously been released, e.g. has a beta or later API file
+        // checked in, then we must verify "release compatibility" against the work-in-progress
+        // API file.
+        val checkResourceApiRelease = project.getRequiredCompatibilityApiLocation()?.let {
+            lastReleasedApiFile ->
+            project.tasks.register(
+                CHECK_RESOURCE_API_RELEASE_TASK,
+                CheckResourceApiReleaseTask::class.java
+            ) { task ->
+                task.referenceApiFile.set(lastReleasedApiFile.resourceFile)
+                task.apiFile.set(builtApiFile)
+                task.dependsOn(packageResTask)
+                task.cacheEvenIfNoOutputs()
+            }
+        }
+
+        // Policy: All changes to API surfaces for which compatibility is enforced must be
+        // explicitly confirmed by running the updateApi task. To enforce this, the implementation
+        // checks the "work-in-progress" built API file against the checked in current API file.
+        val checkResourceApi = project.tasks.register(
+            CHECK_RESOURCE_API_TASK,
+            CheckResourceApiTask::class.java
+        ) { task ->
+            task.group = TASK_GROUP_API
+            task.description = "Checks that the resource API generated from source matches the " +
+                    "checked in resource API file"
+            task.builtApi.set(builtApiFile)
+            task.dependsOn(packageResTask)
+            task.cacheEvenIfNoOutputs()
+            task.checkedInApis.set(outputApiFiles)
+            checkResourceApiRelease?.let {
+                task.dependsOn(it)
+            }
+        }
+
+        val updateResourceApi = project.tasks.register(
+            UPDATE_RESOURCE_API_TASK,
+            UpdateResourceApiTask::class.java
+        ) { task ->
+            task.group = TASK_GROUP_API
+            task.description = "Updates the checked in resource API files to match source code API"
+            task.inputApiFile.set(builtApiFile)
+            task.dependsOn(packageResTask)
+            task.outputApiLocations.set(outputApiLocations)
+            checkResourceApiRelease?.let {
+                // If a developer (accidentally) makes a non-backwards compatible change to an
+                // API, the developer will want to be informed of it as soon as possible.
+                // So, whenever a developer updates an API, if backwards compatibility checks are
+                // enabled in the library, then we want to check that the changes are backwards
+                // compatible
+                task.dependsOn(it)
+            }
+        }
+
+        // Ensure that this task runs as part of updateApi and buildOnServer
+        project.tasks.withType(UpdateApiTask::class.java).configureEach { task ->
+            task.dependsOn(updateResourceApi)
+        }
+        project.addToBuildOnServer(checkResourceApi)
+    }
+}
diff --git a/buildSrc/src/main/kotlin/androidx/build/resources/UpdateResourceApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/resources/UpdateResourceApiTask.kt
new file mode 100644
index 0000000..50aae01
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/resources/UpdateResourceApiTask.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.build.resources
+
+import androidx.build.checkapi.ApiLocation
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.OutputFiles
+import org.gradle.api.tasks.TaskAction
+import java.io.File
+import java.nio.file.Files
+import java.util.SortedSet
+
+/**
+ * Task for updating the public Android resource surface, e.g. `public.xml`.
+ */
+abstract class UpdateResourceApiTask : DefaultTask() {
+    /**
+     * Text file from which resource API signatures will be read.
+     *
+     * A file path must be specified but the file may not exist if the library has no resources.
+     */
+    @get:Internal
+    abstract val inputApiFile: RegularFileProperty
+
+    @InputFile
+    @Optional
+    fun getInputApiFileIfExists(): File? {
+        val file = inputApiFile.get().asFile
+        return if (file.exists()) {
+            file
+        } else {
+            null
+        }
+    }
+
+    /** Text files to which resource signatures will be written. */
+    @get:Internal // outputs are declared in getTaskOutputs()
+    abstract val outputApiLocations: ListProperty<ApiLocation>
+
+    @OutputFiles
+    fun getTaskOutputs(): List<File> {
+        return outputApiLocations.get().flatMap { outputApiLocation ->
+            listOf(
+                outputApiLocation.resourceFile
+            )
+        }
+    }
+
+    @TaskAction
+    fun updateResourceApi() {
+        var permitOverwriting = true
+        for (outputApi in outputApiLocations.get()) {
+            val version = outputApi.version()
+            if (version != null && version.isFinalApi() &&
+                outputApi.publicApiFile.exists() &&
+                !project.hasProperty("force")) {
+                permitOverwriting = false
+            }
+        }
+
+        val inputApi = inputApiFile.get().asFile
+
+        // Read the current API surface, if any, into memory.
+        val inputApiSet = if (inputApi.exists()) {
+            HashSet(inputApi.readLines())
+        } else {
+            emptySet<String>()
+        }
+
+        // Sort the resources for the sake of source control diffs.
+        val inputApiSortedSet: SortedSet<String> = inputApiSet.toSortedSet()
+
+        // Write current API surface to temporary file.
+        val tempApi = Files.createTempFile("res-api", "txt").toFile()
+        tempApi.deleteOnExit()
+        tempApi.bufferedWriter().use { out ->
+            inputApiSortedSet.forEach { api ->
+                out.write(api)
+                out.newLine()
+            }
+        }
+
+        for (outputApi in outputApiLocations.get()) {
+            androidx.build.metalava.copy(
+                tempApi,
+                outputApi.resourceFile,
+                permitOverwriting,
+                project.logger
+            )
+        }
+    }
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
index 8412743..e5dd64f 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
@@ -16,6 +16,8 @@
 
 package androidx.camera.camera2.pipe
 
+import java.io.Closeable
+
 /**
  * A CameraGraph represents the combined configuration and state of a camera.
  */
@@ -23,8 +25,30 @@
     fun start()
     fun stop()
 
+    /**
+     * Acquire and exclusive access to the CameraGraph in a suspending fashion.
+     */
+    suspend fun acquireSession(): Session
+
+    /**
+     * Try acquiring an exclusive access the CameraGraph. Returns null if it can't be acquired
+     * immediately.
+     */
+    fun acquireSessionOrNull(): Session?
+
     data class Config(
         val camera: CameraId,
         val streams: List<StreamConfig>
     )
+
+    /**
+     * A lock on CameraGraph. It facilitates an exclusive access to the managed camera device. Once
+     * this is acquired, a well ordered set of requests can be sent to the camera device without the
+     * possibility of being intermixed with any other request to the camera from non lock holders.
+     */
+    interface Session : Closeable {
+        fun submit(request: Request)
+        fun submit(requests: List<Request>)
+        fun setRepeating(request: Request)
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt
new file mode 100644
index 0000000..60e4c85
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.camera.camera2.pipe
+
+/**
+ * An immutable package of settings and outputs needed to capture a single image from the camera
+ * device.
+ */
+interface Request : RequestMetadata {
+    val streamIds: List<StreamId>
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphImpl.kt
index dc2decb..7563990 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphImpl.kt
@@ -25,6 +25,9 @@
     private val context: Context,
     private val config: CameraGraph.Config
 ) : CameraGraph {
+    // Only one session can be active at a time.
+    private val sessionLock = TokenLockImpl(1)
+
     override fun start() {
         Log.debug { "Starting Camera Graph!" }
         TODO("Not Implemented")
@@ -33,4 +36,14 @@
     override fun stop() {
         TODO("Not Implemented")
     }
+
+    override suspend fun acquireSession(): CameraGraph.Session {
+        val token = sessionLock.acquire(1)
+        return CameraGraphSessionImpl(token)
+    }
+
+    override fun acquireSessionOrNull(): CameraGraph.Session? {
+        val token = sessionLock.acquireOrNull(1) ?: return null
+        return CameraGraphSessionImpl(token)
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphSessionImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphSessionImpl.kt
new file mode 100644
index 0000000..c0b1058
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraGraphSessionImpl.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.camera.camera2.pipe.impl
+
+import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.Request
+
+class CameraGraphSessionImpl(private val token: TokenLock.Token) : CameraGraph.Session {
+    override fun submit(request: Request) {
+        TODO("not implemented")
+    }
+
+    override fun submit(requests: List<Request>) {
+        TODO("not implemented")
+    }
+
+    override fun setRepeating(request: Request) {
+        TODO("not implemented")
+    }
+
+    override fun close() {
+        // Release the token so that a new instance of session can be created.
+        token.release()
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
index e3c225f..dce2657 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
@@ -24,6 +24,8 @@
 import androidx.camera.camera2.pipe.CameraId
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.annotation.Config
@@ -34,12 +36,45 @@
 @DoNotInstrument
 @Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
 class CameraGraphImplTest {
-    @Test
-    fun createCameraGraphImpl() {
+    private lateinit var impl: CameraGraphImpl
+
+    @Before
+    fun setUp() {
         val config = CameraGraph.Config(CameraId("0"), listOf())
         val context = ApplicationProvider.getApplicationContext() as Context
+        impl = CameraGraphImpl(context, config)
+    }
 
-        val impl = CameraGraphImpl(context, config)
+    @Test
+    fun createCameraGraphImpl() {
         assertThat(impl).isNotNull()
     }
+
+    @Test
+    fun testAcquireSession() = runBlocking<Unit> {
+        val session = impl.acquireSession()
+        assertThat(session).isNotNull()
+    }
+
+    @Test
+    fun testAcquireSessionOrNull() {
+        val session = impl.acquireSessionOrNull()
+        assertThat(session).isNotNull()
+    }
+
+    @Test
+    fun testAcquireSessionOrNullAfterAcquireSession() = runBlocking<Unit> {
+        val session = impl.acquireSession()
+        assertThat(session).isNotNull()
+
+        // Since a session is already active, an attempt to acquire another session will fail.
+        val session1 = impl.acquireSessionOrNull()
+        assertThat(session1).isNull()
+
+        // Closing an active session should allow a new session instance to be created.
+        session.close()
+
+        val session2 = impl.acquireSessionOrNull()
+        assertThat(session2).isNotNull()
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
index 0630e97..8b6bfd4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
@@ -800,7 +800,7 @@
 
         // we need to set Camera2OptionUnpacker to the Config to enable the camera2 callback hookup.
         @Override
-        protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(
+        public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(
                 @Nullable CameraInfo cameraInfo) {
             return new FakeUseCaseConfig.Builder()
                     .setSessionOptionUnpacker(new Camera2SessionOptionUnpacker());
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/util/FakeRepeatingUseCase.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/util/FakeRepeatingUseCase.java
index c4698c3..12fb119 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/util/FakeRepeatingUseCase.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/util/FakeRepeatingUseCase.java
@@ -52,7 +52,7 @@
     }
 
     @Override
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         return new FakeUseCaseConfig.Builder()
                 .setSessionOptionUnpacker(
                         (useCaseConfig, sessionConfigBuilder) -> {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index a9f9852..3832620 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -65,7 +65,6 @@
 import com.google.common.util.concurrent.ListenableFuture;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -164,7 +163,7 @@
     final Set<CaptureSession> mConfiguringForClose = new HashSet<>();
 
     // The metering repeating use case for ImageCapture only case.
-    private MeteringRepeating mMeteringRepeating;
+    private MeteringRepeatingSession mMeteringRepeatingSession;
 
     /**
      * Constructor for a camera.
@@ -556,8 +555,10 @@
             //  UseCase has been unbound. The try-catch is to retain existing behavior where an
             //  unbound UseCase is silently ignored.
             try {
-                mUseCaseAttachState.setUseCaseActive(useCase);
-                mUseCaseAttachState.updateUseCase(useCase);
+                mUseCaseAttachState.setUseCaseActive(useCase.getName() + useCase.hashCode(),
+                        useCase.getSessionConfig());
+                mUseCaseAttachState.updateUseCase(useCase.getName() + useCase.hashCode(),
+                        useCase.getSessionConfig());
                 updateCaptureSessionConfig();
             } catch (NullPointerException e) {
                 debugLog("Failed to set already detached use case active");
@@ -572,7 +573,7 @@
         Preconditions.checkNotNull(useCase);
         mExecutor.execute(() -> {
             debugLog("Use case " + useCase + " INACTIVE");
-            mUseCaseAttachState.setUseCaseInactive(useCase);
+            mUseCaseAttachState.setUseCaseInactive(useCase.getName() + useCase.hashCode());
             updateCaptureSessionConfig();
         });
     }
@@ -583,7 +584,8 @@
         Preconditions.checkNotNull(useCase);
         mExecutor.execute(() -> {
             debugLog("Use case " + useCase + " UPDATED");
-            mUseCaseAttachState.updateUseCase(useCase);
+            mUseCaseAttachState.updateUseCase(useCase.getName() + useCase.hashCode(),
+                    useCase.getSessionConfig());
             updateCaptureSessionConfig();
         });
     }
@@ -593,7 +595,8 @@
         Preconditions.checkNotNull(useCase);
         mExecutor.execute(() -> {
             debugLog("Use case " + useCase + " RESET");
-            mUseCaseAttachState.updateUseCase(useCase);
+            mUseCaseAttachState.updateUseCase(useCase.getName() + useCase.hashCode(),
+                    useCase.getSessionConfig());
 
             resetCaptureSession(/*abortInFlightCaptures=*/false);
             updateCaptureSessionConfig();
@@ -621,7 +624,9 @@
             return CallbackToFutureAdapter.<Boolean>getFuture(completer -> {
                 try {
                     mExecutor.execute(
-                            () -> completer.set(mUseCaseAttachState.isUseCaseAttached(useCase)));
+                            () -> completer.set(
+                                    mUseCaseAttachState.isUseCaseAttached(
+                                            useCase.getName() + useCase.hashCode())));
                 } catch (RejectedExecutionException e) {
                     completer.setException(new RuntimeException("Unable to check if use case is "
                             + "attached. Camera executor shut down."));
@@ -651,12 +656,13 @@
         // Figure out which use cases are not already attached and add them.
         List<UseCase> useCasesToAttach = new ArrayList<>();
         for (UseCase useCase : toAdd) {
-            if (!mUseCaseAttachState.isUseCaseAttached(useCase)) {
+            if (!mUseCaseAttachState.isUseCaseAttached(useCase.getName() + useCase.hashCode())) {
                 // TODO(b/150208070): Race condition where onUseCaseActive can be called, even
                 //  after a UseCase has been unbound. The try-catch is to retain existing behavior
                 //  where an unbound UseCase is silently ignored.
                 try {
-                    mUseCaseAttachState.setUseCaseAttached(useCase);
+                    mUseCaseAttachState.setUseCaseAttached(useCase.getName() + useCase.hashCode(),
+                            useCase.getSessionConfig());
 
                     useCasesToAttach.add(useCase);
                 } catch (NullPointerException e) {
@@ -743,8 +749,8 @@
     private void tryDetachUseCases(@NonNull Collection<UseCase> toRemove) {
         List<UseCase> useCasesToDetach = new ArrayList<>();
         for (UseCase useCase : toRemove) {
-            if (mUseCaseAttachState.isUseCaseAttached(useCase)) {
-                mUseCaseAttachState.setUseCaseDetached(useCase);
+            if (mUseCaseAttachState.isUseCaseAttached(useCase.getName() + useCase.hashCode())) {
+                mUseCaseAttachState.setUseCaseDetached(useCase.getName() + useCase.hashCode());
                 useCasesToDetach.add(useCase);
             }
         }
@@ -762,7 +768,7 @@
         // Check if need to add or remove MeetingRepeatingUseCase.
         addOrRemoveMeteringRepeatingUseCase();
 
-        boolean allUseCasesDetached = mUseCaseAttachState.getAttachedUseCases().isEmpty();
+        boolean allUseCasesDetached = mUseCaseAttachState.getAttachedSessionConfigs().isEmpty();
         if (allUseCasesDetached) {
             mCameraControlInternal.setActive(false);
             resetCaptureSession(/*abortInFlightCaptures=*/false);
@@ -791,8 +797,8 @@
         if (!sessionConfig.getSurfaces().isEmpty()) {
             if (captureConfig.getSurfaces().isEmpty()) {
                 // Create the MeteringRepeating UseCase
-                if (mMeteringRepeating == null) {
-                    mMeteringRepeating = new MeteringRepeating(this);
+                if (mMeteringRepeatingSession == null) {
+                    mMeteringRepeatingSession = new MeteringRepeatingSession();
                 }
                 addMeteringRepeating();
             } else {
@@ -813,19 +819,25 @@
         }
     }
 
-    private  void removeMeteringRepeating() {
-        if (mMeteringRepeating != null) {
-            mUseCaseAttachState.setUseCaseDetached(mMeteringRepeating);
-            notifyStateDetachedToUseCases(Arrays.asList(mMeteringRepeating));
-            mMeteringRepeating.clear();
-            mMeteringRepeating = null;
+    private void removeMeteringRepeating() {
+        if (mMeteringRepeatingSession != null) {
+            mUseCaseAttachState.setUseCaseDetached(
+                    mMeteringRepeatingSession.getName() + mMeteringRepeatingSession.hashCode());
+            mUseCaseAttachState.setUseCaseInactive(
+                    mMeteringRepeatingSession.getName() + mMeteringRepeatingSession.hashCode());
+            mMeteringRepeatingSession.clear();
+            mMeteringRepeatingSession = null;
         }
     }
 
-    private  void addMeteringRepeating() {
-        if (mMeteringRepeating != null) {
-            mUseCaseAttachState.setUseCaseAttached(mMeteringRepeating);
-            notifyStateAttachedToUseCases(Arrays.asList(mMeteringRepeating));
+    private void addMeteringRepeating() {
+        if (mMeteringRepeatingSession != null) {
+            mUseCaseAttachState.setUseCaseAttached(
+                    mMeteringRepeatingSession.getName() + mMeteringRepeatingSession.hashCode(),
+                    mMeteringRepeatingSession.getSessionConfig());
+            mUseCaseAttachState.setUseCaseActive(
+                    mMeteringRepeatingSession.getName() + mMeteringRepeatingSession.hashCode(),
+                    mMeteringRepeatingSession.getSessionConfig());
         }
     }
 
@@ -955,12 +967,12 @@
                 } else if (t instanceof CancellationException) {
                     debugLog("Unable to configure camera cancelled");
                 } else if (t instanceof DeferrableSurface.SurfaceClosedException) {
-                    UseCase useCase =
-                            findUseCaseForSurface(
+                    SessionConfig sessionConfig =
+                            findSessionConfigForSurface(
                                     ((DeferrableSurface.SurfaceClosedException) t)
                                             .getDeferrableSurface());
-                    if (useCase != null) {
-                        postSurfaceClosedError(useCase);
+                    if (sessionConfig != null) {
+                        postSurfaceClosedError(sessionConfig);
                     }
                 } else if (t instanceof TimeoutException) {
                     // TODO: Consider to handle the timeout error.
@@ -1006,11 +1018,10 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     @Nullable
     @ExecutedBy("mExecutor")
-    UseCase findUseCaseForSurface(@NonNull DeferrableSurface surface) {
-        for (UseCase useCase : mUseCaseAttachState.getAttachedUseCases()) {
-            SessionConfig sessionConfig = Preconditions.checkNotNull(useCase.getSessionConfig());
+    SessionConfig findSessionConfigForSurface(@NonNull DeferrableSurface surface) {
+        for (SessionConfig sessionConfig : mUseCaseAttachState.getAttachedSessionConfigs()) {
             if (sessionConfig.getSurfaces().contains(surface)) {
-                return useCase;
+                return sessionConfig;
             }
         }
 
@@ -1018,15 +1029,14 @@
     }
 
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-    void postSurfaceClosedError(@NonNull UseCase useCase) {
+    void postSurfaceClosedError(@NonNull SessionConfig sessionConfig) {
         Executor executor = CameraXExecutors.mainThreadExecutor();
-        SessionConfig sessionConfigError = Preconditions.checkNotNull(useCase.getSessionConfig());
         List<SessionConfig.ErrorListener> errorListeners =
-                sessionConfigError.getErrorListeners();
+                sessionConfig.getErrorListeners();
         if (!errorListeners.isEmpty()) {
             SessionConfig.ErrorListener errorListener = errorListeners.get(0);
             debugLog("Posting surface closed", new Throwable());
-            executor.execute(() -> errorListener.onError(sessionConfigError,
+            executor.execute(() -> errorListener.onError(sessionConfig,
                     SessionConfig.SessionError.SESSION_ERROR_SURFACE_NEEDS_RESET));
         }
     }
@@ -1081,10 +1091,8 @@
             return false;
         }
 
-        Collection<UseCase> activeUseCases = mUseCaseAttachState.getActiveAndAttachedUseCases();
-
-        for (UseCase useCase : activeUseCases) {
-            SessionConfig sessionConfig = Preconditions.checkNotNull(useCase.getSessionConfig());
+        for (SessionConfig sessionConfig :
+                mUseCaseAttachState.getActiveAndAttachedSessionConfigs()) {
             // Query the repeating surfaces attached to this use case, then add them to the builder.
             List<DeferrableSurface> surfaces =
                     sessionConfig.getRepeatingCaptureConfig().getSurfaces();
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
index ecdb704..4cb31d8 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
@@ -310,10 +310,6 @@
             cancelFocusAndMeteringWithoutAsyncResult();
         }
 
-        disableAutoCancel();
-        mCurrentFocusMeteringAction = action;
-        mRunningActionCompleter = completer;
-
         Rect cropSensorRegion = mCameraControl.getCropSensorRegion();
         Rational cropRegionAspectRatio = new Rational(cropSensorRegion.width(),
                 cropSensorRegion.height());
@@ -331,6 +327,9 @@
                     defaultAspectRatio);
             MeteringRectangle meteringRectangle = getMeteringRect(meteringPoint, adjustedPoint,
                     cropSensorRegion);
+            if (meteringRectangle.getWidth() == 0 || meteringRectangle.getHeight() == 0) {
+                continue;
+            }
             meteringRectanglesListAF.add(meteringRectangle);
         }
 
@@ -339,6 +338,9 @@
                     defaultAspectRatio);
             MeteringRectangle meteringRectangle = getMeteringRect(meteringPoint, adjustedPoint,
                     cropSensorRegion);
+            if (meteringRectangle.getWidth() == 0 || meteringRectangle.getHeight() == 0) {
+                continue;
+            }
             meteringRectanglesListAE.add(meteringRectangle);
         }
 
@@ -347,9 +349,25 @@
                     defaultAspectRatio);
             MeteringRectangle meteringRectangle = getMeteringRect(meteringPoint, adjustedPoint,
                     cropSensorRegion);
+            if (meteringRectangle.getWidth() == 0 || meteringRectangle.getHeight() == 0) {
+                continue;
+            }
             meteringRectanglesListAWB.add(meteringRectangle);
         }
 
+        if (meteringRectanglesListAF.isEmpty()
+                && meteringRectanglesListAE.isEmpty()
+                && meteringRectanglesListAWB.isEmpty()) {
+            completer.setException(
+                    new IllegalArgumentException("None of the specified AF/AE/AWB MeteringPoints "
+                            + "are valid."));
+            return;
+        }
+
+        disableAutoCancel();
+        mCurrentFocusMeteringAction = action;
+        mRunningActionCompleter = completer;
+
         executeMeteringAction(
                 meteringRectanglesListAF.toArray(new MeteringRectangle[0]),
                 meteringRectanglesListAE.toArray(new MeteringRectangle[0]),
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeating.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeating.java
deleted file mode 100644
index e2b7152..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeating.java
+++ /dev/null
@@ -1,134 +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.camera.camera2.internal;
-
-import android.graphics.SurfaceTexture;
-import android.hardware.camera2.CameraDevice;
-import android.util.Log;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.camera.core.CameraInfo;
-import androidx.camera.core.UseCase;
-import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.DeferrableSurface;
-import androidx.camera.core.impl.ImmediateSurface;
-import androidx.camera.core.impl.SessionConfig;
-import androidx.camera.core.impl.UseCaseConfig;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-
-/**
- * A use case that only used in Camera2 to act a Metering repeating use case.
- *
- * <p> When ImageCapture only to do the action of takePicture, the MeteringRepeatingUseCase is
- * created in Camera2 layer to make Camera2 have the repeating surface to metering the auto 3A or
- * wait for 3A converged.
- *
- */
-public class MeteringRepeating extends UseCase {
-
-    private static final String TAG = "MeteringRepeating";
-    private DeferrableSurface mDeferrableSurface;
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    /**
-     * Creates a new instance of a {@link MeteringRepeating} with a given configuration.
-     * @param config for this use case instance
-     */
-    public MeteringRepeating(@NonNull MeteringRepeatingConfig config) {
-        super(config);
-    }
-
-
-    /**
-     * * Creates a new instance of a {@link MeteringRepeating} with a CameraInternal and
-     * default configuration.
-     *
-     * @param cameraInternal for this use case instance
-     *
-     */
-    public MeteringRepeating(@NonNull CameraInternal cameraInternal) {
-
-        this(new MeteringRepeatingConfig.Builder().getUseCaseConfig());
-
-        // attach to the Camera
-        onAttach(cameraInternal);
-
-        updateSuggestedResolution(new Size(640, 480));
-    }
-
-    @NonNull
-    @Override
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
-        return new MeteringRepeatingConfig.Builder()
-                .setSessionOptionUnpacker(new Camera2SessionOptionUnpacker());
-    }
-
-    @Override
-    public void clear() {
-        notifyInactive();
-        if (DEBUG) {
-            Log.d(TAG, "MeteringRepeating clear!");
-        }
-        if (mDeferrableSurface != null) {
-            mDeferrableSurface.close();
-        }
-        mDeferrableSurface = null;
-        super.clear();
-    }
-
-    @Override
-    @NonNull
-    protected Size onSuggestedResolutionUpdated(@NonNull Size suggestedResolution) {
-        MeteringRepeatingConfig configWithDefaults = (MeteringRepeatingConfig) getUseCaseConfig();
-
-        // Create the metering DeferrableSurface
-        SurfaceTexture surfaceTexture = new SurfaceTexture(0);
-        surfaceTexture.setDefaultBufferSize(0, 0);
-        Surface surface = new Surface(surfaceTexture);
-
-        SessionConfig.Builder builder = SessionConfig.Builder.createFrom(configWithDefaults);
-        builder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
-
-        if (mDeferrableSurface != null) {
-            mDeferrableSurface.close();
-        }
-
-        mDeferrableSurface = new ImmediateSurface(surface);
-        mDeferrableSurface.getTerminationFuture().addListener(() -> {
-            if (DEBUG) {
-                Log.d(TAG, "Release metering surface and surface texture");
-            }
-            surface.release();
-            surfaceTexture.release();
-        }, CameraXExecutors.directExecutor());
-        builder.addSurface(mDeferrableSurface);
-
-        updateSessionConfig(builder.build());
-        // TODO(b/153826101): Try to set the MeteringRepeating use case to be active when a
-        //  pre-capture sequence is needed.This could significantly reduce battery consumption
-        //  when pictures are not being taken.
-        notifyActive();
-
-        return new Size(0, 0);
-    }
-
-}
-
-
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java
deleted file mode 100644
index f38d5d6..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java
+++ /dev/null
@@ -1,189 +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.camera.camera2.internal;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.CameraSelector;
-import androidx.camera.core.UseCase;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.Config;
-import androidx.camera.core.impl.MutableConfig;
-import androidx.camera.core.impl.MutableOptionsBundle;
-import androidx.camera.core.impl.OptionsBundle;
-import androidx.camera.core.impl.SessionConfig;
-import androidx.camera.core.impl.UseCaseConfig;
-import androidx.camera.core.internal.TargetConfig;
-
-import java.util.UUID;
-
-/**
- * Configuration for a {@link MeteringRepeating} use case.
- */
-public class MeteringRepeatingConfig implements UseCaseConfig<MeteringRepeating> {
-
-    private final OptionsBundle mConfig;
-
-    /** Creates a new configuration instance. */
-    public MeteringRepeatingConfig(@NonNull OptionsBundle config) {
-        mConfig = config;
-    }
-
-    @NonNull
-    @Override
-    public Config getConfig() {
-        return mConfig;
-    }
-
-    /** Builder for an empty Config */
-    public static final class Builder implements
-            UseCaseConfig.Builder<MeteringRepeating, MeteringRepeatingConfig, Builder> {
-
-        private final MutableOptionsBundle mMutableConfig;
-
-        /** Creates a new Builder object. */
-        public Builder() {
-            this(MutableOptionsBundle.create());
-        }
-
-        private Builder(MutableOptionsBundle mutableConfig) {
-            mMutableConfig = mutableConfig;
-
-            Class<?> oldConfigClass =
-                    mutableConfig.retrieveOption(TargetConfig.OPTION_TARGET_CLASS, null);
-            if (oldConfigClass != null && !oldConfigClass.equals(MeteringRepeating.class)) {
-                throw new IllegalArgumentException(
-                        "Invalid target class configuration for "
-                                + MeteringRepeatingConfig.Builder.this
-                                + ": "
-                                + oldConfigClass);
-            }
-
-            setTargetClass(MeteringRepeating.class);
-        }
-
-        /**
-         * Generates a Builder from another Config object
-         *
-         * @param configuration An immutable configuration to pre-populate this builder.
-         * @return The new Builder.
-         */
-        @NonNull
-        public static MeteringRepeatingConfig.Builder fromConfig(
-                @NonNull MeteringRepeatingConfig configuration) {
-            return new MeteringRepeatingConfig.Builder(MutableOptionsBundle.from(configuration));
-        }
-
-
-        @NonNull
-        @Override
-        public MutableConfig getMutableConfig() {
-            return mMutableConfig;
-        }
-
-        @NonNull
-        @Override
-        public MeteringRepeatingConfig getUseCaseConfig() {
-            return new MeteringRepeatingConfig(OptionsBundle.from(mMutableConfig));
-        }
-
-
-        @NonNull
-        @Override
-        public MeteringRepeating build() {
-            return new MeteringRepeating(getUseCaseConfig());
-        }
-
-        // Implementations of TargetConfig.Builder default methods
-
-        @NonNull
-        @Override
-        public Builder setTargetClass(@NonNull Class<MeteringRepeating> targetClass) {
-            getMutableConfig().insertOption(OPTION_TARGET_CLASS, targetClass);
-
-            // If no name is set yet, then generate a unique name
-            if (null == getMutableConfig().retrieveOption(OPTION_TARGET_NAME, null)) {
-                String targetName = targetClass.getCanonicalName() + "-" + UUID.randomUUID();
-                setTargetName(targetName);
-            }
-
-            return this;
-
-        }
-
-        @NonNull
-        @Override
-        public Builder setTargetName(@NonNull String targetName) {
-            getMutableConfig().insertOption(OPTION_TARGET_NAME, targetName);
-            return this;
-        }
-
-
-        // Implementations of UseCaseConfig.Builder default methods
-        @NonNull
-        @Override
-        public Builder setDefaultSessionConfig(@NonNull SessionConfig sessionConfig) {
-            getMutableConfig().insertOption(OPTION_DEFAULT_SESSION_CONFIG, sessionConfig);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setDefaultCaptureConfig(@NonNull CaptureConfig captureConfig) {
-            getMutableConfig().insertOption(OPTION_DEFAULT_CAPTURE_CONFIG, captureConfig);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setSessionOptionUnpacker(
-                @NonNull SessionConfig.OptionUnpacker optionUnpacker) {
-            getMutableConfig().insertOption(OPTION_SESSION_CONFIG_UNPACKER, optionUnpacker);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setCaptureOptionUnpacker(
-                @NonNull CaptureConfig.OptionUnpacker optionUnpacker) {
-            getMutableConfig().insertOption(OPTION_CAPTURE_CONFIG_UNPACKER, optionUnpacker);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setSurfaceOccupancyPriority(int priority) {
-            getMutableConfig().insertOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, priority);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setCameraSelector(@NonNull CameraSelector cameraSelector) {
-            getMutableConfig().insertOption(OPTION_CAMERA_SELECTOR, cameraSelector);
-            return this;
-        }
-
-        @NonNull
-        @Override
-        public Builder setUseCaseEventCallback(@NonNull UseCase.EventCallback eventCallback) {
-            getMutableConfig().insertOption(OPTION_USE_CASE_EVENT_CALLBACK, eventCallback);
-            return this;
-        }
-
-    }
-}
-
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java
new file mode 100644
index 0000000..b36775f
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingSession.java
@@ -0,0 +1,121 @@
+/*
+ * 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.camera.camera2.internal;
+
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraDevice;
+import android.util.Log;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.UseCase;
+import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.DeferrableSurface;
+import androidx.camera.core.impl.ImmediateSurface;
+import androidx.camera.core.impl.MutableOptionsBundle;
+import androidx.camera.core.impl.SessionConfig;
+import androidx.camera.core.impl.UseCaseConfig;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
+
+/**
+ * A SessionConfig to act a Metering repeating use case.
+ *
+ * <p> When ImageCapture only to do the action of takePicture, the MeteringRepeating is
+ * created in Camera2 layer to make Camera2 have the repeating surface to metering the auto 3A or
+ * wait for 3A converged.
+ *
+ */
+class MeteringRepeatingSession {
+    private static final String TAG = "MeteringRepeating";
+    private DeferrableSurface mDeferrableSurface;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    @NonNull
+    private final SessionConfig mSessionConfig;
+
+    /** Creates a new instance of a {@link MeteringRepeatingSession}. */
+    MeteringRepeatingSession() {
+        MeteringRepeatingConfig configWithDefaults = new MeteringRepeatingConfig();
+
+        // Create the metering DeferrableSurface
+        SurfaceTexture surfaceTexture = new SurfaceTexture(0);
+        surfaceTexture.setDefaultBufferSize(0, 0);
+        Surface surface = new Surface(surfaceTexture);
+
+        SessionConfig.Builder builder = SessionConfig.Builder.createFrom(configWithDefaults);
+        builder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
+
+        mDeferrableSurface = new ImmediateSurface(surface);
+        mDeferrableSurface.getTerminationFuture().addListener(() -> {
+            if (DEBUG) {
+                Log.d(TAG, "Release metering surface and surface texture");
+            }
+            surface.release();
+            surfaceTexture.release();
+        }, CameraXExecutors.directExecutor());
+        builder.addSurface(mDeferrableSurface);
+
+        mSessionConfig = builder.build();
+    }
+
+    @NonNull
+    SessionConfig getSessionConfig() {
+        return mSessionConfig;
+    }
+
+    @NonNull
+    String getName() {
+        return "MeteringRepeating";
+    }
+
+    /**
+     * The {@link MeteringRepeatingSession} should only be used once and afterwards should be
+     * cleared.
+     */
+    void clear() {
+        if (DEBUG) {
+            Log.d(TAG, "MeteringRepeating clear!");
+        }
+        if (mDeferrableSurface != null) {
+            mDeferrableSurface.close();
+        }
+        mDeferrableSurface = null;
+    }
+
+    /**
+     * A minimal config that contains a {@link SessionConfig.OptionUnpacker} in order to unpack
+     * the camera2 related options.
+     */
+    private static class MeteringRepeatingConfig implements UseCaseConfig<UseCase> {
+        @NonNull
+        private final Config mConfig;
+        MeteringRepeatingConfig() {
+            MutableOptionsBundle mutableOptionsBundle = MutableOptionsBundle.create();
+            mutableOptionsBundle.insertOption(UseCaseConfig.OPTION_SESSION_CONFIG_UNPACKER,
+                    new Camera2SessionOptionUnpacker());
+            mConfig = mutableOptionsBundle;
+        }
+
+        @NonNull
+        @Override
+        public Config getConfig() {
+            return mConfig;
+        }
+    }
+}
+
+
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/FocusMeteringControlTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/FocusMeteringControlTest.java
index 407d9eb..f98693a 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/FocusMeteringControlTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/FocusMeteringControlTest.java
@@ -496,8 +496,7 @@
     @Test
     public void withAFPoints_AFIsTriggered() {
         mFocusMeteringControl.startFocusAndMetering(new FocusMeteringAction.Builder(mPoint1,
-                FLAG_AF | FLAG_AE | FLAG_AWB).build(),
-                PREVIEW_ASPECT_RATIO_4_X_3);
+                        FLAG_AF | FLAG_AE | FLAG_AWB).build(), PREVIEW_ASPECT_RATIO_4_X_3);
 
         verify(mFocusMeteringControl).triggerAf(any());
         Mockito.reset(mFocusMeteringControl);
@@ -670,15 +669,14 @@
         captureResultListener.onCaptureResult(result);
     }
 
-    private static <T> void assertFutureFailedWithOperationCancelation(ListenableFuture<T> future) {
+    private static <T> void assertFutureFailedWithOperationCancelation(ListenableFuture<T> future)
+            throws Exception {
         try {
             future.get();
         } catch (ExecutionException e) {
             assertThat(e.getCause()).isInstanceOf(CameraControl.OperationCanceledException.class);
             return;
-        } catch (Exception e) {
         }
-
         fail("Should fail with CameraControl.OperationCanceledException.");
     }
 
@@ -888,7 +886,7 @@
 
     @Test
     public void startThenCancelThenStart_previous2FuturesFailsWithOperationCancelled()
-            throws ExecutionException, InterruptedException, TimeoutException {
+            throws Exception {
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1)
                 .build();
 
@@ -918,8 +916,7 @@
     }
 
     @Test
-    public void startMultipleActions_cancelNonLatest()
-            throws ExecutionException, InterruptedException, TimeoutException {
+    public void startMultipleActions_cancelNonLatest() throws Exception {
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1)
                 .build();
 
@@ -1070,7 +1067,7 @@
     }
 
     @Test
-    public void cancelFocusMetering_actionIsCancelledAndfutureCompletes() {
+    public void cancelFocusMetering_actionIsCancelledAndfutureCompletes() throws Exception {
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1).build();
         ListenableFuture<FocusMeteringResult> actionResult =
                 mFocusMeteringControl.startFocusAndMetering(action,
@@ -1150,7 +1147,7 @@
     }
 
     @Test
-    public void startFocusMeteringAFAEAWB_noPointsAreSupported_failFuture() {
+    public void startFocusMeteringAFAEAWB_noPointsAreSupported_failFuture() throws Exception {
         FocusMeteringControl focusMeteringControl = initFocusMeteringControl(CAMERA3_ID);
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1,
                 FLAG_AF | FLAG_AE | FLAG_AWB).build();
@@ -1164,14 +1161,13 @@
         } catch (ExecutionException e) {
             assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
             return;
-        } catch (Exception e) {
         }
 
         fail("Future should fail with IllegalArgumentException.");
     }
 
     @Test
-    public void startFocusMeteringAEAWB_noPointsAreSupported_failFuture() {
+    public void startFocusMeteringAEAWB_noPointsAreSupported_failFuture() throws Exception {
         FocusMeteringControl focusMeteringControl = initFocusMeteringControl(CAMERA3_ID);
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1,
                 FLAG_AE | FLAG_AWB).build();
@@ -1185,14 +1181,13 @@
         } catch (ExecutionException e) {
             assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
             return;
-        } catch (Exception e) {
         }
 
         fail("Future should fail with IllegalArgumentException.");
     }
 
     @Test
-    public void startFocusMeteringAFAWB_noPointsAreSupported_failFuture() {
+    public void startFocusMeteringAFAWB_noPointsAreSupported_failFuture() throws Exception {
         FocusMeteringControl focusMeteringControl = initFocusMeteringControl(CAMERA3_ID);
         FocusMeteringAction action = new FocusMeteringAction.Builder(mPoint1,
                 FLAG_AF | FLAG_AWB).build();
@@ -1205,7 +1200,6 @@
         } catch (ExecutionException e) {
             assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
             return;
-        } catch (Exception e) {
         }
 
         fail("Future should fail with IllegalArgumentException.");
@@ -1218,8 +1212,8 @@
         // regions.  it should still complete the future.
         FocusMeteringAction action =
                 new FocusMeteringAction.Builder(mPoint1, FLAG_AE | FLAG_AWB)
-                .addPoint(mPoint2, FLAG_AWB)
-                .build();
+                        .addPoint(mPoint2, FLAG_AWB)
+                        .build();
 
         ListenableFuture<FocusMeteringResult> future =
                 mFocusMeteringControl.startFocusAndMetering(action,
@@ -1237,4 +1231,32 @@
 
         assertFutureFocusCompleted(future, false);
     }
+
+    @Test
+    public void startFocusMetering_noPointsAreValid_failFuture() throws Exception {
+        FocusMeteringControl focusMeteringControl = initFocusMeteringControl(CAMERA0_ID);
+
+        // These will generate MeteringRectangles (width == 0 or height ==0)
+        final MeteringPoint invalidPt1 = mPointFactory.createPoint(2.0f, 2.0f);
+        final MeteringPoint invalidPt2 = mPointFactory.createPoint(2.0f, 0.5f);
+        final MeteringPoint invalidPt3 = mPointFactory.createPoint(-1.0f, -1.0f);
+
+        FocusMeteringAction action =
+                new FocusMeteringAction.Builder(invalidPt1, FLAG_AF)
+                        .addPoint(invalidPt2, FLAG_AE)
+                        .addPoint(invalidPt3, FLAG_AWB).build();
+
+        ListenableFuture<FocusMeteringResult> future =
+                focusMeteringControl.startFocusAndMetering(action,
+                        PREVIEW_ASPECT_RATIO_4_X_3);
+        try {
+            future.get(500, TimeUnit.MILLISECONDS);
+        } catch (ExecutionException e) {
+            assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
+            return;
+        }
+
+        fail("Future should fail with IllegalArgumentException.");
+    }
+
 }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ForwardingImageReaderListenerTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ForwardingImageReaderListenerTest.java
deleted file mode 100644
index 5984d1d..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ForwardingImageReaderListenerTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.graphics.ImageFormat;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.impl.ImageReaderProxy;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public final class ForwardingImageReaderListenerTest {
-    private static final int IMAGE_WIDTH = 640;
-    private static final int IMAGE_HEIGHT = 480;
-    private static final int IMAGE_FORMAT = ImageFormat.YUV_420_888;
-    private static final int MAX_IMAGES = 10;
-
-    private final ImageReaderProxy mImageReader = mock(ImageReaderProxy.class);
-    private final Surface mSurface = mock(Surface.class);
-    private List<QueuedImageReaderProxy> mImageReaderProxies;
-    private ForwardingImageReaderListener mForwardingListener;
-    private ExecutorService mExecutor;
-
-    private static ImageProxy createMockImage() {
-        ImageProxy image = mock(ImageProxy.class);
-        when(image.getWidth()).thenReturn(IMAGE_WIDTH);
-        when(image.getHeight()).thenReturn(IMAGE_HEIGHT);
-        when(image.getFormat()).thenReturn(IMAGE_FORMAT);
-        return image;
-    }
-
-    private static ImageReaderProxy.OnImageAvailableListener createMockListener() {
-        return mock(ImageReaderProxy.OnImageAvailableListener.class);
-    }
-
-    /**
-     * Returns a listener which immediately acquires the next image, closes the image, and releases
-     * a semaphore.
-     */
-    private static ImageReaderProxy.OnImageAvailableListener
-            createSemaphoreReleasingClosingListener(final Semaphore semaphore) {
-        return new ImageReaderProxy.OnImageAvailableListener() {
-            @Override
-            public void onImageAvailable(@NonNull ImageReaderProxy imageReaderProxy) {
-                imageReaderProxy.acquireNextImage().close();
-                semaphore.release();
-            }
-        };
-    }
-
-    @Before
-    public void setUp() {
-        mExecutor = Executors.newSingleThreadExecutor();
-        mImageReaderProxies = new ArrayList<>(3);
-        for (int i = 0; i < 3; ++i) {
-            mImageReaderProxies.add(
-                    new QueuedImageReaderProxy(
-                            IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_FORMAT, MAX_IMAGES, mSurface));
-        }
-        mForwardingListener = new ForwardingImageReaderListener(mImageReaderProxies);
-    }
-
-    @After
-    public void tearDown() {
-        mExecutor.shutdown();
-    }
-
-    @Test
-    public void newImageIsForwardedToAllListeners() {
-        ImageProxy baseImage = createMockImage();
-        when(mImageReader.acquireNextImage()).thenReturn(baseImage);
-        List<ImageReaderProxy.OnImageAvailableListener> listeners = new ArrayList<>();
-        for (ImageReaderProxy imageReaderProxy : mImageReaderProxies) {
-            ImageReaderProxy.OnImageAvailableListener listener = createMockListener();
-            imageReaderProxy.setOnImageAvailableListener(listener, mExecutor);
-            listeners.add(listener);
-        }
-
-        final int availableImages = 5;
-        for (int i = 0; i < availableImages; ++i) {
-            mForwardingListener.onImageAvailable(mImageReader);
-        }
-
-        for (int i = 0; i < mImageReaderProxies.size(); ++i) {
-            // Listener should be notified about every available image.
-            verify(listeners.get(i), timeout(2000).times(availableImages))
-                    .onImageAvailable(mImageReaderProxies.get(i));
-        }
-    }
-
-    @Test
-    public void baseImageIsClosed_allQueuesAreCleared_whenAllForwardedCopiesAreClosed()
-            throws InterruptedException {
-        Semaphore onCloseSemaphore = new Semaphore(/*permits=*/ 0);
-        ImageProxy baseImage = createMockImage();
-        when(mImageReader.acquireNextImage()).thenReturn(baseImage);
-        for (ImageReaderProxy imageReaderProxy : mImageReaderProxies) {
-            // Close the image for every listener.
-            imageReaderProxy.setOnImageAvailableListener(
-                    createSemaphoreReleasingClosingListener(onCloseSemaphore), mExecutor);
-        }
-
-        final int availableImages = 5;
-        for (int i = 0; i < availableImages; ++i) {
-            mForwardingListener.onImageAvailable(mImageReader);
-        }
-        onCloseSemaphore.acquire(availableImages * mImageReaderProxies.size());
-
-        // Base image should be closed every time.
-        verify(baseImage, times(availableImages)).close();
-        // All queues should be cleared.
-        for (QueuedImageReaderProxy imageReaderProxy : mImageReaderProxies) {
-            assertThat(imageReaderProxy.getCurrentImages()).isEqualTo(0);
-        }
-    }
-
-    @Test
-    public void baseImageIsNotClosed_someQueuesAreCleared_whenNotAllForwardedCopiesAreClosed()
-            throws InterruptedException {
-        Semaphore onCloseSemaphore = new Semaphore(/*permits=*/ 0);
-        ImageProxy baseImage = createMockImage();
-        when(mImageReader.acquireNextImage()).thenReturn(baseImage);
-        // Don't close the image for the first listener.
-        mImageReaderProxies.get(0).setOnImageAvailableListener(createMockListener(), mExecutor);
-        // Close the image for the other listeners.
-        mImageReaderProxies
-                .get(1)
-                .setOnImageAvailableListener(
-                        createSemaphoreReleasingClosingListener(onCloseSemaphore), mExecutor);
-        mImageReaderProxies
-                .get(2)
-                .setOnImageAvailableListener(
-                        createSemaphoreReleasingClosingListener(onCloseSemaphore), mExecutor);
-
-        final int availableImages = 5;
-        for (int i = 0; i < availableImages; ++i) {
-            mForwardingListener.onImageAvailable(mImageReader);
-        }
-        onCloseSemaphore.acquire(availableImages * (mImageReaderProxies.size() - 1));
-
-        // Base image should not be closed every time.
-        verify(baseImage, never()).close();
-        // First reader's queue should not be cleared.
-        assertThat(mImageReaderProxies.get(0).getCurrentImages()).isEqualTo(availableImages);
-        // Other readers' queues should be cleared.
-        assertThat(mImageReaderProxies.get(1).getCurrentImages()).isEqualTo(0);
-        assertThat(mImageReaderProxies.get(2).getCurrentImages()).isEqualTo(0);
-    }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/QueuedImageReaderProxyTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/QueuedImageReaderProxyTest.java
deleted file mode 100644
index 2c4565b..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/QueuedImageReaderProxyTest.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import android.graphics.ImageFormat;
-import android.view.Surface;
-
-import androidx.camera.core.impl.ImageReaderProxy;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public final class QueuedImageReaderProxyTest {
-    private static final int IMAGE_WIDTH = 640;
-    private static final int IMAGE_HEIGHT = 480;
-    private static final int IMAGE_FORMAT = ImageFormat.YUV_420_888;
-    private static final int MAX_IMAGES = 10;
-
-    private final Surface mSurface = mock(Surface.class);
-    private ExecutorService mExecutor;
-    private QueuedImageReaderProxy mImageReaderProxy;
-
-    private static ImageProxy createMockImageProxy() {
-        ImageProxy image = mock(ImageProxy.class);
-        when(image.getWidth()).thenReturn(IMAGE_WIDTH);
-        when(image.getHeight()).thenReturn(IMAGE_HEIGHT);
-        when(image.getFormat()).thenReturn(IMAGE_FORMAT);
-        return image;
-    }
-
-    private static ConcreteImageProxy createSemaphoreReleasingOnCloseImageProxy(
-            final Semaphore semaphore) {
-        ConcreteImageProxy image = createForwardingImageProxy();
-        image.addOnImageCloseListener(
-                new ForwardingImageProxy.OnImageCloseListener() {
-                    @Override
-                    public void onImageClose(ImageProxy closedImage) {
-                        semaphore.release();
-                    }
-                });
-        return image;
-    }
-
-    private static ConcreteImageProxy createForwardingImageProxy() {
-        return new ConcreteImageProxy(createMockImageProxy());
-    }
-
-    @Before
-    public void setUp() {
-        mExecutor = Executors.newSingleThreadExecutor();
-        mImageReaderProxy =
-                new QueuedImageReaderProxy(
-                        IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_FORMAT, MAX_IMAGES, mSurface);
-    }
-
-    @After
-    public void tearDown() {
-        mExecutor.shutdown();
-    }
-
-    @Test
-    public void enqueueImage_incrementsQueueSize() {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-
-        assertThat(mImageReaderProxy.getCurrentImages()).isEqualTo(2);
-    }
-
-    @Test
-    public void enqueueImage_doesNotIncreaseSizeBeyondMaxImages() {
-        // Exceed the queue's capacity by 2.
-        for (int i = 0; i < MAX_IMAGES + 2; ++i) {
-            mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        }
-
-        assertThat(mImageReaderProxy.getCurrentImages()).isEqualTo(MAX_IMAGES);
-    }
-
-    @Test
-    public void enqueueImage_closesImagesWhichAreNotEnqueued_doesNotCloseOtherImages() {
-        // Exceed the queue's capacity by 2.
-        List<ConcreteImageProxy> images = new ArrayList<>(MAX_IMAGES + 2);
-        for (int i = 0; i < MAX_IMAGES + 2; ++i) {
-            images.add(createForwardingImageProxy());
-            mImageReaderProxy.enqueueImage(images.get(i));
-        }
-
-        // Last two images should not be enqueued and should be closed.
-        assertThat(images.get(MAX_IMAGES).isClosed()).isTrue();
-        assertThat(images.get(MAX_IMAGES + 1).isClosed()).isTrue();
-        // All other images should be enqueued and open.
-        for (int i = 0; i < MAX_IMAGES; ++i) {
-            assertThat(images.get(i).isClosed()).isFalse();
-        }
-    }
-
-    @Test
-    public void closedImages_reduceQueueSize() throws InterruptedException {
-        // Fill up to the queue's capacity.
-        Semaphore onCloseSemaphore = new Semaphore(/*permits=*/ 0);
-        for (int i = 0; i < MAX_IMAGES; ++i) {
-            ForwardingImageProxy image =
-                    createSemaphoreReleasingOnCloseImageProxy(onCloseSemaphore);
-            mImageReaderProxy.enqueueImage(image);
-        }
-
-        mImageReaderProxy.acquireNextImage().close();
-        mImageReaderProxy.acquireNextImage().close();
-        onCloseSemaphore.acquire(/*permits=*/ 2);
-
-        assertThat(mImageReaderProxy.getCurrentImages()).isEqualTo(MAX_IMAGES - 2);
-    }
-
-    @Test
-    public void closedImage_allowsNewImageToBeEnqueued() throws InterruptedException {
-        // Fill up to the queue's capacity.
-        Semaphore onCloseSemaphore = new Semaphore(/*permits=*/ 0);
-        for (int i = 0; i < MAX_IMAGES; ++i) {
-            ForwardingImageProxy image =
-                    createSemaphoreReleasingOnCloseImageProxy(onCloseSemaphore);
-            mImageReaderProxy.enqueueImage(image);
-        }
-
-        mImageReaderProxy.acquireNextImage().close();
-        onCloseSemaphore.acquire();
-
-        ConcreteImageProxy lastImageProxy = createForwardingImageProxy();
-        mImageReaderProxy.enqueueImage(lastImageProxy);
-
-        // Last image should be enqueued and open.
-        assertThat(lastImageProxy.isClosed()).isFalse();
-    }
-
-    @Test
-    public void enqueueImage_invokesListenerCallbackOnExecutor() {
-        ImageReaderProxy.OnImageAvailableListener listener =
-                mock(ImageReaderProxy.OnImageAvailableListener.class);
-        mImageReaderProxy.setOnImageAvailableListener(listener, mExecutor);
-        enqueueImage_invokesListenerCallback(listener);
-    }
-
-    private void enqueueImage_invokesListenerCallback(
-            ImageReaderProxy.OnImageAvailableListener listener) {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-
-        verify(listener, timeout(2000).times(2)).onImageAvailable(mImageReaderProxy);
-    }
-
-    @Test
-    public void listenerNotInvoked_afterItIsCleared() {
-        ImageReaderProxy.OnImageAvailableListener listener =
-                mock(ImageReaderProxy.OnImageAvailableListener.class);
-        mImageReaderProxy.setOnImageAvailableListener(listener, mExecutor);
-
-        mImageReaderProxy.clearOnImageAvailableListener();
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-
-        verifyZeroInteractions(listener);
-    }
-
-    @Test
-    public void acquireLatestImage_returnsNull_whenQueueIsEmpty() {
-        assertThat(mImageReaderProxy.acquireLatestImage()).isNull();
-    }
-
-    @Test
-    public void acquireLatestImage_returnsLastImage_reducesQueueSizeToOne() {
-        final int availableImages = 5;
-        List<ForwardingImageProxy> images = new ArrayList<>(availableImages);
-        for (int i = 0; i < availableImages; ++i) {
-            images.add(createForwardingImageProxy());
-            mImageReaderProxy.enqueueImage(images.get(i));
-        }
-
-        ImageProxy lastImage = images.get(availableImages - 1);
-        assertThat(mImageReaderProxy.acquireLatestImage()).isEqualTo(lastImage);
-        assertThat(mImageReaderProxy.getCurrentImages()).isEqualTo(1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void acquireLatestImage_throwsException_whenAllImagesWerePreviouslyAcquired() {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.acquireNextImage();
-
-        // Should throw IllegalStateException
-        mImageReaderProxy.acquireLatestImage();
-    }
-
-    @Test
-    public void acquireNextImage_returnsNull_whenQueueIsEmpty() {
-        assertThat(mImageReaderProxy.acquireNextImage()).isNull();
-    }
-
-    @Test
-    public void acquireNextImage_returnsNextImage_doesNotChangeQueueSize() {
-        final int availableImages = 5;
-        List<ForwardingImageProxy> images = new ArrayList<>(availableImages);
-        for (int i = 0; i < availableImages; ++i) {
-            images.add(createForwardingImageProxy());
-            mImageReaderProxy.enqueueImage(images.get(i));
-        }
-
-        for (int i = 0; i < availableImages; ++i) {
-            assertThat(mImageReaderProxy.acquireNextImage()).isEqualTo(images.get(i));
-        }
-        assertThat(mImageReaderProxy.getCurrentImages()).isEqualTo(availableImages);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void acquireNextImage_throwsException_whenAllImagesWerePreviouslyAcquired() {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.acquireNextImage();
-
-        // Should throw IllegalStateException
-        mImageReaderProxy.acquireNextImage();
-    }
-
-    @Test
-    public void close_closesAnyImagesStillInQueue() {
-        ConcreteImageProxy image0 = createForwardingImageProxy();
-        ConcreteImageProxy image1 = createForwardingImageProxy();
-        mImageReaderProxy.enqueueImage(image0);
-        mImageReaderProxy.enqueueImage(image1);
-
-        mImageReaderProxy.close();
-
-        assertThat(image0.isClosed()).isTrue();
-        assertThat(image1.isClosed()).isTrue();
-    }
-
-    @Test
-    public void close_notifiesOnCloseListeners() {
-        QueuedImageReaderProxy.OnReaderCloseListener listenerA =
-                mock(QueuedImageReaderProxy.OnReaderCloseListener.class);
-        QueuedImageReaderProxy.OnReaderCloseListener listenerB =
-                mock(QueuedImageReaderProxy.OnReaderCloseListener.class);
-        mImageReaderProxy.addOnReaderCloseListener(listenerA);
-        mImageReaderProxy.addOnReaderCloseListener(listenerB);
-
-        mImageReaderProxy.close();
-
-        verify(listenerA, times(1)).onReaderClose(mImageReaderProxy);
-        verify(listenerB, times(1)).onReaderClose(mImageReaderProxy);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void acquireLatestImage_throwsException_afterReaderIsClosed() {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.close();
-
-        // Should throw IllegalStateException
-        mImageReaderProxy.acquireLatestImage();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void acquireNextImage_throwsException_afterReaderIsClosed() {
-        mImageReaderProxy.enqueueImage(createForwardingImageProxy());
-        mImageReaderProxy.close();
-
-        // Should throw IllegalStateException
-        mImageReaderProxy.acquireNextImage();
-    }
-
-    @Test
-    public void getHeight_returnsFixedHeight() {
-        assertThat(mImageReaderProxy.getHeight()).isEqualTo(IMAGE_HEIGHT);
-    }
-
-    @Test
-    public void getWidth_returnsFixedWidth() {
-        assertThat(mImageReaderProxy.getWidth()).isEqualTo(IMAGE_WIDTH);
-    }
-
-    @Test
-    public void getImageFormat_returnsFixedFormat() {
-        assertThat(mImageReaderProxy.getImageFormat()).isEqualTo(IMAGE_FORMAT);
-    }
-
-    @Test
-    public void getMaxImages_returnsFixedCapacity() {
-        assertThat(mImageReaderProxy.getMaxImages()).isEqualTo(MAX_IMAGES);
-    }
-
-    private static final class ConcreteImageProxy extends ForwardingImageProxy {
-        private boolean mIsClosed = false;
-
-        ConcreteImageProxy(ImageProxy image) {
-            super(image);
-        }
-
-        @Override
-        public synchronized void close() {
-            super.close();
-            mIsClosed = true;
-        }
-
-        public synchronized boolean isClosed() {
-            return mIsClosed;
-        }
-    }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ReferenceCountedImageProxyTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ReferenceCountedImageProxyTest.java
deleted file mode 100644
index de9ba46..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ReferenceCountedImageProxyTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ReferenceCountedImageProxyTest {
-    private static final int WIDTH = 640;
-    private static final int HEIGHT = 480;
-
-    // Assume the image has YUV_420_888 format.
-    private final ImageProxy mImage = mock(ImageProxy.class);
-    private final ImageProxy.PlaneProxy mYPlane = mock(ImageProxy.PlaneProxy.class);
-    private final ImageProxy.PlaneProxy mUPlane = mock(ImageProxy.PlaneProxy.class);
-    private final ImageProxy.PlaneProxy mVPlane = mock(ImageProxy.PlaneProxy.class);
-    private final ByteBuffer mYBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT);
-    private final ByteBuffer mUBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT / 4);
-    private final ByteBuffer mVBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT / 4);
-    private ReferenceCountedImageProxy mImageProxy;
-
-    @Before
-    public void setUp() {
-        when(mImage.getWidth()).thenReturn(WIDTH);
-        when(mImage.getHeight()).thenReturn(HEIGHT);
-        when(mYPlane.getBuffer()).thenReturn(mYBuffer);
-        when(mUPlane.getBuffer()).thenReturn(mUBuffer);
-        when(mVPlane.getBuffer()).thenReturn(mVBuffer);
-        when(mImage.getPlanes()).thenReturn(new ImageProxy.PlaneProxy[]{mYPlane, mUPlane, mVPlane});
-        mImageProxy = new ReferenceCountedImageProxy(mImage);
-    }
-
-    @Test
-    public void getReferenceCount_returnsOne_afterConstruction() {
-        assertThat(mImageProxy.getReferenceCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void fork_incrementsReferenceCount() {
-        mImageProxy.fork();
-        mImageProxy.fork();
-
-        assertThat(mImageProxy.getReferenceCount()).isEqualTo(3);
-    }
-
-    @Test
-    public void close_decrementsReferenceCount() {
-        ImageProxy forkedImage0 = mImageProxy.fork();
-        ImageProxy forkedImage1 = mImageProxy.fork();
-
-        forkedImage0.close();
-        forkedImage1.close();
-
-        assertThat(mImageProxy.getReferenceCount()).isEqualTo(1);
-        verify(mImage, never()).close();
-    }
-
-    @Test
-    public void close_closesBaseImage_whenReferenceCountHitsZero() {
-        ImageProxy forkedImage0 = mImageProxy.fork();
-        ImageProxy forkedImage1 = mImageProxy.fork();
-
-        forkedImage0.close();
-        forkedImage1.close();
-        mImageProxy.close();
-
-        assertThat(mImageProxy.getReferenceCount()).isEqualTo(0);
-        verify(mImage, times(1)).close();
-    }
-
-    @Test
-    public void close_decrementsReferenceCountOnlyOnce() {
-        ImageProxy forkedImage = mImageProxy.fork();
-
-        forkedImage.close();
-        forkedImage.close();
-
-        assertThat(mImageProxy.getReferenceCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void fork_returnsNull_whenBaseImageIsClosed() {
-        mImageProxy.close();
-
-        ImageProxy forkedImage = mImageProxy.fork();
-
-        assertThat(forkedImage).isNull();
-    }
-
-    @Test
-    public void concurrentAccessForTwoForkedImagesOnTwoThreads() throws InterruptedException {
-        final ImageProxy forkedImage0 = mImageProxy.fork();
-        final ImageProxy forkedImage1 = mImageProxy.fork();
-
-        Thread thread0 =
-                new Thread() {
-                    @Override
-                    public void run() {
-                        forkedImage0.getWidth();
-                        forkedImage0.getHeight();
-                        ImageProxy.PlaneProxy[] planes = forkedImage0.getPlanes();
-                        for (ImageProxy.PlaneProxy plane : planes) {
-                            ByteBuffer buffer = plane.getBuffer();
-                            for (int i = 0; i < buffer.capacity(); ++i) {
-                                buffer.get(i);
-                            }
-                        }
-                    }
-                };
-        Thread thread1 =
-                new Thread() {
-                    @Override
-                    public void run() {
-                        forkedImage1.getWidth();
-                        forkedImage1.getHeight();
-                        ImageProxy.PlaneProxy[] planes = forkedImage1.getPlanes();
-                        for (ImageProxy.PlaneProxy plane : planes) {
-                            ByteBuffer buffer = plane.getBuffer();
-                            for (int i = 0; i < buffer.capacity(); ++i) {
-                                buffer.get(i);
-                            }
-                        }
-                    }
-                };
-
-        thread0.start();
-        thread1.start();
-        thread0.join();
-        thread1.join();
-    }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
index 4d0a5ef..46f919a 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
@@ -18,6 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.camera.testing.fakes.FakeCamera;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
 import androidx.camera.testing.fakes.FakeLifecycleOwner;
 import androidx.camera.testing.fakes.FakeUseCase;
 import androidx.lifecycle.LifecycleOwner;
@@ -28,6 +31,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Collections;
 import java.util.Map;
 
 @SmallTest
@@ -37,12 +41,15 @@
     private FakeLifecycleOwner mLifecycle;
     private UseCaseMediatorRepository mRepository;
     private Map<LifecycleOwner, UseCaseMediatorLifecycleController> mUseCasesMap;
+    private CameraUseCaseAdapter mCameraUseCaseAdapter;
 
     @Before
     public void setUp() {
         mLifecycle = new FakeLifecycleOwner();
         mRepository = new UseCaseMediatorRepository();
         mUseCasesMap = mRepository.getUseCasesMap();
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(new FakeCamera(),
+                new FakeCameraDeviceSurfaceManager());
     }
 
     @Test
@@ -99,12 +106,15 @@
     }
 
     @Test
-    public void useCaseIsCleared_whenLifecycleIsDestroyed() {
+    public void useCaseIsCleared_whenLifecycleIsDestroyed()
+            throws CameraUseCaseAdapter.CameraException {
         UseCaseMediatorLifecycleController mediator = mRepository.getOrCreateUseCaseMediator(
                 mLifecycle);
         FakeUseCase useCase = new FakeUseCase();
         mediator.getUseCaseMediator().addUseCase(useCase);
 
+        mCameraUseCaseAdapter.attachUseCases(Collections.singleton(useCase));
+
         assertThat(useCase.isCleared()).isFalse();
 
         mLifecycle.destroy();
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.java
index d2a7647..0d00d8f 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseTest.java
@@ -70,8 +70,9 @@
         FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
                 "UseCase").getUseCaseConfig();
         TestUseCase testUseCase = new TestUseCase(config);
+
         testUseCase.onAttach(mMockCameraInternal);
-        testUseCase.onDetach();
+        testUseCase.onDetach(mMockCameraInternal);
 
         testUseCase.activate();
 
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseAttachStateTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseAttachStateTest.java
index 951dddc..f472720 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseAttachStateTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseAttachStateTest.java
@@ -18,83 +18,40 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assume.assumeTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import android.content.Context;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
-import android.util.Size;
 import android.view.Surface;
 
-import androidx.annotation.NonNull;
-import androidx.camera.core.CameraSelector;
-import androidx.camera.core.CameraX;
-import androidx.camera.core.CameraXConfig;
-import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.DeferrableSurfacesUtil;
-import androidx.camera.testing.fakes.FakeAppConfig;
-import androidx.camera.testing.fakes.FakeUseCase;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
-import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 
-@LargeTest
+@MediumTest
 @RunWith(AndroidJUnit4.class)
 public class UseCaseAttachStateTest {
     private final CameraDevice mMockCameraDevice = mock(CameraDevice.class);
     private final CameraCaptureSession mMockCameraCaptureSession =
             mock(CameraCaptureSession.class);
 
-    private String mCameraId;
-    private List<TestUseCase> mTestUseCases = new ArrayList<>();
-
-    @Before
-    public void setUp() throws ExecutionException, InterruptedException {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
-
-        CameraXConfig cameraXConfig = FakeAppConfig.create();
-        Context context = ApplicationProvider.getApplicationContext();
-        CameraX.initialize(context, cameraXConfig).get();
-        mCameraId = CameraUtil.getCameraIdWithLensFacing(CameraSelector.LENS_FACING_BACK);
-        if (mCameraId == null) {
-            throw new IllegalArgumentException("Unable to attach to camera with LensFacing "
-                    + CameraSelector.LENS_FACING_BACK);
-        }
-    }
-
-    @After
-    public void tearDown() throws ExecutionException, InterruptedException {
-        for (TestUseCase useCase : mTestUseCases) {
-            useCase.clear();
-        }
-        mTestUseCases.clear();
-        CameraX.shutdown().get();
-    }
+    private String mCameraId = "cameraId";
 
     @Test
     public void setSingleUseCaseOnline() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config =
-                new FakeUseCaseConfig.Builder()
-                        .setTargetName("UseCase")
-                        .getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider fakeUseCase = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
+        useCaseAttachState.setUseCaseAttached(fakeUseCase.getName(),
+                fakeUseCase.getSessionConfig());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -121,15 +78,13 @@
     @Test
     public void setTwoUseCasesOnline() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase0 = createTestUseCase(config0, CameraSelector.DEFAULT_BACK_CAMERA);
-        FakeUseCaseConfig config1 = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase1 = createTestUseCase(config1, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider fakeUseCase0 = new TestUseCaseDataProvider();
+        TestUseCaseDataProvider fakeUseCase1 = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase0);
-        useCaseAttachState.setUseCaseAttached(fakeUseCase1);
+        useCaseAttachState.setUseCaseAttached(fakeUseCase0.getName(),
+                fakeUseCase0.getSessionConfig());
+        useCaseAttachState.setUseCaseAttached(fakeUseCase1.getName(),
+                fakeUseCase1.getSessionConfig());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -161,11 +116,9 @@
     @Test
     public void setUseCaseActiveOnly() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider fakeUseCase = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseActive(fakeUseCase);
+        useCaseAttachState.setUseCaseActive(fakeUseCase.getName(), fakeUseCase.getSessionConfig());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getActiveAndAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -191,12 +144,11 @@
     @Test
     public void setUseCaseActiveAndOnline() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider fakeUseCase = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
-        useCaseAttachState.setUseCaseActive(fakeUseCase);
+        useCaseAttachState.setUseCaseAttached(fakeUseCase.getName(),
+                fakeUseCase.getSessionConfig());
+        useCaseAttachState.setUseCaseActive(fakeUseCase.getName(), fakeUseCase.getSessionConfig());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getActiveAndAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -223,12 +175,11 @@
     @Test
     public void setUseCaseOffline() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider testUseCaseDataProvider = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
-        useCaseAttachState.setUseCaseDetached(fakeUseCase);
+        useCaseAttachState.setUseCaseAttached(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
+        useCaseAttachState.setUseCaseDetached(testUseCaseDataProvider.getName());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -237,30 +188,31 @@
         for (CameraDevice.StateCallback callback : sessionConfig.getDeviceStateCallbacks()) {
             callback.onOpened(mMockCameraDevice);
         }
-        verify(fakeUseCase.mDeviceStateCallback, never()).onOpened(mMockCameraDevice);
+        verify(testUseCaseDataProvider.mDeviceStateCallback, never()).onOpened(mMockCameraDevice);
 
         for (CameraCaptureSession.StateCallback callback
                 : sessionConfig.getSessionStateCallbacks()) {
             callback.onConfigured(mMockCameraCaptureSession);
         }
-        verify(fakeUseCase.mSessionStateCallback, never()).onConfigured(mMockCameraCaptureSession);
+        verify(testUseCaseDataProvider.mSessionStateCallback, never()).onConfigured(
+                mMockCameraCaptureSession);
 
         for (CameraCaptureCallback callback : sessionConfig.getRepeatingCameraCaptureCallbacks()) {
             callback.onCaptureCompleted(null);
         }
-        verify(fakeUseCase.mCameraCaptureCallback, never()).onCaptureCompleted(null);
+        verify(testUseCaseDataProvider.mCameraCaptureCallback, never()).onCaptureCompleted(null);
     }
 
     @Test
     public void setUseCaseInactive() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider testUseCaseDataProvider = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
-        useCaseAttachState.setUseCaseActive(fakeUseCase);
-        useCaseAttachState.setUseCaseInactive(fakeUseCase);
+        useCaseAttachState.setUseCaseAttached(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
+        useCaseAttachState.setUseCaseActive(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
+        useCaseAttachState.setUseCaseInactive(testUseCaseDataProvider.getName());
 
         SessionConfig.ValidatingBuilder builder = useCaseAttachState.getActiveAndAttachedBuilder();
         SessionConfig sessionConfig = builder.build();
@@ -269,40 +221,40 @@
         for (CameraDevice.StateCallback callback : sessionConfig.getDeviceStateCallbacks()) {
             callback.onOpened(mMockCameraDevice);
         }
-        verify(fakeUseCase.mDeviceStateCallback, never()).onOpened(mMockCameraDevice);
+        verify(testUseCaseDataProvider.mDeviceStateCallback, never()).onOpened(mMockCameraDevice);
 
         for (CameraCaptureSession.StateCallback callback
                 : sessionConfig.getSessionStateCallbacks()) {
             callback.onConfigured(mMockCameraCaptureSession);
         }
-        verify(fakeUseCase.mSessionStateCallback, never()).onConfigured(mMockCameraCaptureSession);
+        verify(testUseCaseDataProvider.mSessionStateCallback, never()).onConfigured(
+                mMockCameraCaptureSession);
 
         for (CameraCaptureCallback callback : sessionConfig.getRepeatingCameraCaptureCallbacks()) {
             callback.onCaptureCompleted(null);
         }
-        verify(fakeUseCase.mCameraCaptureCallback, never()).onCaptureCompleted(null);
+        verify(testUseCaseDataProvider.mCameraCaptureCallback, never()).onCaptureCompleted(null);
     }
 
     @Test
     public void updateUseCase() {
         UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_BACK_CAMERA);
+        TestUseCaseDataProvider testUseCaseDataProvider = new TestUseCaseDataProvider();
 
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
-        useCaseAttachState.setUseCaseActive(fakeUseCase);
+        useCaseAttachState.setUseCaseAttached(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
+        useCaseAttachState.setUseCaseActive(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
 
         // The original template should be PREVIEW.
         SessionConfig firstSessionConfig = useCaseAttachState.getActiveAndAttachedBuilder().build();
         assertThat(firstSessionConfig.getTemplateType()).isEqualTo(CameraDevice.TEMPLATE_PREVIEW);
 
         // Change the template to STILL_CAPTURE.
-        SessionConfig.Builder builder = new SessionConfig.Builder();
-        builder.setTemplateType(CameraDevice.TEMPLATE_STILL_CAPTURE);
-        fakeUseCase.updateSessionConfig(builder.build());
+        testUseCaseDataProvider.setTemplateType(CameraDevice.TEMPLATE_STILL_CAPTURE);
 
-        useCaseAttachState.updateUseCase(fakeUseCase);
+        useCaseAttachState.updateUseCase(testUseCaseDataProvider.getName(),
+                testUseCaseDataProvider.getSessionConfig());
 
         // The new template should be STILL_CAPTURE.
         SessionConfig secondSessionConfig =
@@ -311,39 +263,7 @@
                 .isEqualTo(CameraDevice.TEMPLATE_STILL_CAPTURE);
     }
 
-    @Test(expected = IllegalArgumentException.class)
-    public void setUseCaseOnlineWithWrongCamera() {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
-
-        UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_FRONT_CAMERA);
-
-        // Should throw IllegalArgumentException
-        useCaseAttachState.setUseCaseAttached(fakeUseCase);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void setUseCaseActiveWithWrongCamera() {
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
-
-        UseCaseAttachState useCaseAttachState = new UseCaseAttachState(mCameraId);
-        FakeUseCaseConfig config = new FakeUseCaseConfig.Builder().setTargetName(
-                "UseCase").getUseCaseConfig();
-        TestUseCase fakeUseCase = createTestUseCase(config, CameraSelector.DEFAULT_FRONT_CAMERA);
-
-        // Should throw IllegalArgumentException
-        useCaseAttachState.setUseCaseActive(fakeUseCase);
-    }
-
-    private TestUseCase createTestUseCase(FakeUseCaseConfig config, CameraSelector selector) {
-        TestUseCase testUseCase = new TestUseCase(config, selector);
-        mTestUseCases.add(testUseCase);
-        return testUseCase;
-    }
-
-    private static class TestUseCase extends FakeUseCase {
+    private static class TestUseCaseDataProvider {
         private final Surface mSurface = mock(Surface.class);
         private final CameraDevice.StateCallback mDeviceStateCallback =
                 mock(CameraDevice.StateCallback.class);
@@ -352,18 +272,30 @@
         private final CameraCaptureCallback mCameraCaptureCallback =
                 mock(CameraCaptureCallback.class);
         private DeferrableSurface mDeferrableSurface;
+        private int mTemplateType = CameraDevice.TEMPLATE_PREVIEW;
 
-        TestUseCase(FakeUseCaseConfig config, CameraSelector selector) {
-            super(config);
-            onAttach(CameraX.getCameraWithCameraSelector(selector));
-            updateSuggestedResolution(new Size(640, 480));
+        private SessionConfig mSessionConfig;
+
+        TestUseCaseDataProvider() {
+            buildSessionConfig();
         }
 
-        @Override
-        @NonNull
-        protected Size onSuggestedResolutionUpdated(@NonNull Size suggestedResolution) {
+        void setTemplateType(int templateType) {
+            mTemplateType = templateType;
+            buildSessionConfig();
+        }
+
+        SessionConfig getSessionConfig() {
+            return mSessionConfig;
+        }
+
+        String getName() {
+            return toString();
+        }
+
+        private void buildSessionConfig() {
             SessionConfig.Builder builder = new SessionConfig.Builder();
-            builder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
+            builder.setTemplateType(mTemplateType);
             if (mDeferrableSurface != null) {
                 mDeferrableSurface.close();
             }
@@ -373,23 +305,7 @@
             builder.addSessionStateCallback(mSessionStateCallback);
             builder.addRepeatingCameraCaptureCallback(mCameraCaptureCallback);
 
-            updateSessionConfig(builder.build());
-
-            return suggestedResolution;
+            mSessionConfig = builder.build();
         }
-
-        @Override
-        public void clear() {
-            super.clear();
-            if (mDeferrableSurface != null) {
-                mDeferrableSurface.close();
-            }
-        }
-
-        @Override
-        public void updateSessionConfig(@NonNull SessionConfig sessionConfig) {
-            super.updateSessionConfig(sessionConfig);
-        }
-
     }
 }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
index f27efe7..2dec264 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
@@ -18,12 +18,16 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import androidx.camera.core.FakeOtherUseCase;
 import androidx.camera.core.FakeOtherUseCaseConfig;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.camera.testing.fakes.FakeCamera;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
 import androidx.camera.testing.fakes.FakeUseCase;
 import androidx.camera.testing.fakes.FakeUseCaseConfig;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -32,16 +36,19 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
+
+import java.util.Collections;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class UseCaseMediatorTest {
     private final UseCaseMediator.StateChangeCallback mMockCallback =
-            Mockito.mock(UseCaseMediator.StateChangeCallback.class);
+            mock(UseCaseMediator.StateChangeCallback.class);
     private UseCaseMediator mUseCaseMediator;
     private FakeUseCase mFakeUseCase;
     private FakeOtherUseCase mFakeOtherUseCase;
+    private CameraUseCaseAdapter mCameraUseCaseAdapter;
+    private CameraInternal mMockCamera = mock(CameraInternal.class);
 
     @Before
     public void setUp() {
@@ -52,6 +59,8 @@
                 new FakeOtherUseCaseConfig.Builder()
                         .setTargetName("fakeOtherUseCaseConfig")
                         .getUseCaseConfig();
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(new FakeCamera(),
+                new FakeCameraDeviceSurfaceManager());
         mUseCaseMediator = new UseCaseMediator();
         mFakeUseCase = new FakeUseCase(fakeUseCaseConfig);
         mFakeOtherUseCase = new FakeOtherUseCase(fakeOtherUseCaseConfig);
@@ -77,16 +86,22 @@
     }
 
     @Test
-    public void mediatorBecomesEmpty_afterMediatorIsCleared() {
+    public void mediatorBecomesEmpty_afterMediatorIsCleared()
+            throws CameraUseCaseAdapter.CameraException {
         mUseCaseMediator.addUseCase(mFakeUseCase);
+        mCameraUseCaseAdapter.attachUseCases(Collections.singleton(mFakeUseCase));
+
         mUseCaseMediator.destroy();
 
         assertThat(mUseCaseMediator.getUseCases()).isEmpty();
     }
 
     @Test
-    public void useCaseIsCleared_afterMediatorIsCleared() {
+    public void useCaseIsCleared_afterMediatorIsCleared()
+            throws CameraUseCaseAdapter.CameraException {
         mUseCaseMediator.addUseCase(mFakeUseCase);
+        mCameraUseCaseAdapter.attachUseCases(Collections.singleton(mFakeUseCase));
+
         assertThat(mFakeUseCase.isCleared()).isFalse();
 
         mUseCaseMediator.destroy();
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java
new file mode 100644
index 0000000..ba896c6
--- /dev/null
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.camera.core.internal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.camera.testing.fakes.FakeCamera;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
+import androidx.camera.testing.fakes.FakeUseCase;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+
+/** JUnit test cases for {@link CameraUseCaseAdapter} class. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CameraUseCaseAdapterTest {
+    FakeCameraDeviceSurfaceManager mFakeCameraDeviceSurfaceManager;
+    FakeCamera mFakeCamera;
+
+    @Before
+    public void setUp() {
+        mFakeCameraDeviceSurfaceManager = new FakeCameraDeviceSurfaceManager();
+        mFakeCamera =  new FakeCamera();
+    }
+
+    @Test
+    public void attachUseCases() throws CameraUseCaseAdapter.CameraException {
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraDeviceSurfaceManager);
+        FakeUseCase fakeUseCase = new FakeUseCase();
+        cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
+
+        assertThat(fakeUseCase.getCamera()).isEqualTo(mFakeCamera);
+    }
+
+    @Test
+    public void detachUseCases() throws CameraUseCaseAdapter.CameraException {
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraDeviceSurfaceManager);
+        FakeUseCase fakeUseCase = new FakeUseCase();
+        cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
+        cameraUseCaseAdapter.detachUseCases(Collections.singleton(fakeUseCase));
+
+        assertThat(fakeUseCase.getCamera()).isNull();
+    }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/UseCaseOccupancyTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/UseCaseOccupancyTest.java
index f086cc0..eb95728 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/UseCaseOccupancyTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/UseCaseOccupancyTest.java
@@ -35,7 +35,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.concurrent.ExecutionException;
 
 /** JUnit test cases for {@link UseCaseOccupancy} class. */
@@ -62,8 +62,7 @@
         ImageCapture useCase2 = createImageCapture();
 
         assertThat(UseCaseOccupancy.checkUseCaseLimitNotExceeded(
-                Collections.singletonList(useCase1),
-                Collections.singletonList(useCase2))).isFalse();
+                Arrays.asList(useCase1, useCase2))).isFalse();
     }
 
     @Test
@@ -73,8 +72,7 @@
         VideoCapture useCase2 = new VideoCapture(config);
 
         assertThat(UseCaseOccupancy.checkUseCaseLimitNotExceeded(
-                Collections.singletonList(useCase1),
-                Collections.singletonList(useCase2))).isFalse();
+                Arrays.asList(useCase1, useCase2))).isFalse();
     }
 
     @Test
@@ -83,8 +81,7 @@
         VideoCapture videoCapture = new VideoCaptureConfig.Builder().build();
 
         assertThat(UseCaseOccupancy.checkUseCaseLimitNotExceeded(
-                Collections.singletonList(imageCapture),
-                Collections.singletonList(videoCapture))).isTrue();
+                Arrays.asList(imageCapture, videoCapture))).isTrue();
     }
 
     // TODO remove when UseCase does not require
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
index 4139c12..5b13ebd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
@@ -77,8 +77,8 @@
      * supported on current device, only the first point and then in order up to the number of
      * points supported by the device will be enabled.
      *
-     * <p>If none of the points with either AF/AE/AWB can be supported on the device,
-     * the returned {@link ListenableFuture} in
+     * <p>If none of the points with either AF/AE/AWB can be supported on the device or none of
+     * the points generates valid metering rectangles, the returned {@link ListenableFuture} in
      * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} will fail immediately.
      *
      * @see FocusMeteringAction
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index 079901d..b55223d 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -341,8 +341,9 @@
         }
 
         // Only do resolution calculation if UseCases were attached
-        if (!UseCaseOccupancy.checkUseCaseLimitNotExceeded(originalUseCases,
-                Arrays.asList(useCases))) {
+        List<UseCase> totalUseCases = new ArrayList<>(originalUseCases);
+        totalUseCases.addAll(Arrays.asList(useCases));
+        if (!UseCaseOccupancy.checkUseCaseLimitNotExceeded(totalUseCases)) {
             throw new IllegalArgumentException("Attempting to bind too many ImageCapture or "
                     + "VideoCapture instances");
         }
@@ -443,8 +444,9 @@
             }
 
             // Unbind the UseCase from the currently bound camera if it is bound
-            if (wasUnbound) {
-                useCase.onDetach();
+            CameraInternal attachedCamera = useCase.getCamera();
+            if (wasUnbound && attachedCamera != null) {
+                useCase.onDetach(attachedCamera);
                 useCase.onDestroy();
             }
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ForwardingImageReaderListener.java b/camera/camera-core/src/main/java/androidx/camera/core/ForwardingImageReaderListener.java
deleted file mode 100644
index 9924ee3..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/ForwardingImageReaderListener.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.camera.core.impl.ImageReaderProxy;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * An {@link ImageReaderProxy.OnImageAvailableListener} which forks and forwards newly available
- * images to multiple {@link ImageReaderProxy} instances.
- */
-final class ForwardingImageReaderListener implements ImageReaderProxy.OnImageAvailableListener {
-    @GuardedBy("this")
-    private final List<QueuedImageReaderProxy> mImageReaders;
-
-    /**
-     * Creates a new forwarding listener.
-     *
-     * @param imageReaders list of image readers which will receive a copy of every new image
-     * @return new {@link ForwardingImageReaderListener} instance
-     */
-    ForwardingImageReaderListener(List<QueuedImageReaderProxy> imageReaders) {
-        // Make a copy of the incoming List to avoid ConcurrentAccessException.
-        mImageReaders = Collections.unmodifiableList(new ArrayList<>(imageReaders));
-    }
-
-    @Override
-    public synchronized void onImageAvailable(@NonNull ImageReaderProxy imageReaderProxy) {
-        ImageProxy imageProxy = imageReaderProxy.acquireNextImage();
-        if (imageProxy == null) {
-            return;
-        }
-        ReferenceCountedImageProxy referenceCountedImageProxy =
-                new ReferenceCountedImageProxy(imageProxy);
-        for (QueuedImageReaderProxy queuedImageReaderProxy : mImageReaders) {
-            synchronized (queuedImageReaderProxy) {
-                if (!queuedImageReaderProxy.isClosed()) {
-                    ImageProxy forkedImage = referenceCountedImageProxy.fork();
-                    ForwardingImageProxy imageToEnqueue =
-                            ImageProxyDownsampler.downsample(
-                                    forkedImage,
-                                    queuedImageReaderProxy.getWidth(),
-                                    queuedImageReaderProxy.getHeight(),
-                                    ImageProxyDownsampler.DownsamplingMethod.AVERAGING);
-                    queuedImageReaderProxy.enqueueImage(imageToEnqueue);
-                }
-            }
-        }
-        referenceCountedImageProxy.close();
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index be95f0b..a74a15a 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -454,7 +454,7 @@
     @Override
     @Nullable
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         ImageAnalysisConfig defaults = CameraX.getDefaultUseCaseConfig(ImageAnalysisConfig.class,
                 cameraInfo);
         if (defaults != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 079a363..0b0ff6e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -399,7 +399,7 @@
     @Override
     @Nullable
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         ImageCaptureConfig defaults = CameraX.getDefaultUseCaseConfig(ImageCaptureConfig.class,
                 cameraInfo);
         if (defaults != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index 15098c3..aab7373 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -394,7 +394,7 @@
     @Override
     @Nullable
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         PreviewConfig defaults = CameraX.getDefaultUseCaseConfig(PreviewConfig.class, cameraInfo);
         if (defaults != null) {
             return Builder.fromConfig(defaults);
@@ -411,7 +411,7 @@
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    protected UseCaseConfig<?> applyDefaults(
+    public UseCaseConfig<?> applyDefaults(
             @NonNull UseCaseConfig<?> userConfig,
             @Nullable UseCaseConfig.Builder<?, ?, ?> defaultConfigBuilder) {
         PreviewConfig previewConfig = (PreviewConfig) super.applyDefaults(userConfig,
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/QueuedImageReaderProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/QueuedImageReaderProxy.java
deleted file mode 100644
index 80bd3908..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/QueuedImageReaderProxy.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import android.view.Surface;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.camera.core.impl.ImageReaderProxy;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-
-/**
- * An {@link ImageReaderProxy} which maintains a queue of recently available images.
- *
- * <p>Like a conventional {@link android.media.ImageReader}, when the queue becomes full and the
- * user does not close older images quickly enough, newly available images will not be added to the
- * queue and become lost. The user is responsible for setting a listener for newly available images
- * and closing the acquired images quickly enough.
- */
-final class QueuedImageReaderProxy
-        implements ImageReaderProxy, ForwardingImageProxy.OnImageCloseListener {
-    private final int mWidth;
-    private final int mHeight;
-    private final int mFormat;
-    private final int mMaxImages;
-
-    @GuardedBy("this")
-    private final Surface mSurface;
-
-    // mMaxImages is not expected to be large, because images consume a lot of memory and there
-    // cannot
-    // co-exist too many images simultaneously. So, just use a List to simplify the implementation.
-    @GuardedBy("this")
-    private final List<ImageProxy> mImages;
-
-    @GuardedBy("this")
-    private final Set<ImageProxy> mAcquiredImages = new HashSet<>();
-    @GuardedBy("this")
-    private final Set<OnReaderCloseListener> mOnReaderCloseListeners = new HashSet<>();
-    // Current access position in the queue.
-    @GuardedBy("this")
-    private int mCurrentPosition;
-    @GuardedBy("this")
-    @Nullable
-    private ImageReaderProxy.OnImageAvailableListener mOnImageAvailableListener;
-    @GuardedBy("this")
-    @Nullable
-    private Executor mOnImageAvailableExecutor;
-    @GuardedBy("this")
-    private boolean mClosed;
-
-    /**
-     * Creates a new instance of a queued image reader proxy.
-     *
-     * @param width     of the images
-     * @param height    of the images
-     * @param format    of the images
-     * @param maxImages capacity of the queue
-     * @param surface   to which the reader is attached
-     * @return new {@link QueuedImageReaderProxy} instance
-     */
-    QueuedImageReaderProxy(int width, int height, int format, int maxImages, Surface surface) {
-        mWidth = width;
-        mHeight = height;
-        mFormat = format;
-        mMaxImages = maxImages;
-        mSurface = surface;
-        mImages = new ArrayList<>(maxImages);
-        mCurrentPosition = 0;
-        mClosed = false;
-    }
-
-    @Override
-    @Nullable
-    public synchronized ImageProxy acquireLatestImage() {
-        throwExceptionIfClosed();
-        if (mImages.isEmpty()) {
-            return null;
-        }
-        if (mCurrentPosition >= mImages.size()) {
-            throw new IllegalStateException("Max images have already been acquired without close.");
-        }
-
-        // Close all images up to the tail of the list, except for already acquired images.
-        List<ImageProxy> imagesToClose = new ArrayList<>();
-        for (int i = 0; i < mImages.size() - 1; ++i) {
-            if (!mAcquiredImages.contains(mImages.get(i))) {
-                imagesToClose.add(mImages.get(i));
-            }
-        }
-        for (ImageProxy image : imagesToClose) {
-            // Calling image.close() will cause this.onImageClosed(image) to be called.
-            image.close();
-        }
-
-        // Move the current position to the tail of the list.
-        mCurrentPosition = mImages.size() - 1;
-        ImageProxy acquiredImage = mImages.get(mCurrentPosition++);
-        mAcquiredImages.add(acquiredImage);
-        return acquiredImage;
-    }
-
-    @Override
-    @Nullable
-    public synchronized ImageProxy acquireNextImage() {
-        throwExceptionIfClosed();
-        if (mImages.isEmpty()) {
-            return null;
-        }
-        if (mCurrentPosition >= mImages.size()) {
-            throw new IllegalStateException("Max images have already been acquired without close.");
-        }
-        ImageProxy acquiredImage = mImages.get(mCurrentPosition++);
-        mAcquiredImages.add(acquiredImage);
-        return acquiredImage;
-    }
-
-    /**
-     * Adds an image to the tail of the queue.
-     *
-     * <p>If the queue already contains the max number of images, the given image is not added to
-     * the queue and is closed. This is consistent with the documented behavior of an {@link
-     * android.media.ImageReader}, where new images may be lost if older images are not closed
-     * quickly enough.
-     *
-     * <p>If the image is added to the queue and an on-image-available listener has been previously
-     * set, the listener is notified that the new image is available.
-     *
-     * @param image to add
-     */
-    synchronized void enqueueImage(ForwardingImageProxy image) {
-        throwExceptionIfClosed();
-        if (mImages.size() < mMaxImages) {
-            mImages.add(image);
-            image.addOnImageCloseListener(this);
-            if (mOnImageAvailableListener != null && mOnImageAvailableExecutor != null) {
-                final OnImageAvailableListener listener = mOnImageAvailableListener;
-                mOnImageAvailableExecutor.execute(
-                        new Runnable() {
-                            @Override
-                            public void run() {
-                                if (!QueuedImageReaderProxy.this.isClosed()) {
-                                    listener.onImageAvailable(QueuedImageReaderProxy.this);
-                                }
-                            }
-                        });
-            }
-        } else {
-            image.close();
-        }
-    }
-
-    @Override
-    public synchronized void close() {
-        if (!mClosed) {
-            this.mOnImageAvailableExecutor = null;
-            this.mOnImageAvailableListener = null;
-            // We need to copy into a different list, because closing an image triggers the on-close
-            // listener which in turn modifies the original list.
-            List<ImageProxy> imagesToClose = new ArrayList<>(mImages);
-            for (ImageProxy image : imagesToClose) {
-                image.close();
-            }
-            mImages.clear();
-            mClosed = true;
-            notifyOnReaderCloseListeners();
-        }
-    }
-
-    @Override
-    public int getHeight() {
-        throwExceptionIfClosed();
-        return mHeight;
-    }
-
-    @Override
-    public int getWidth() {
-        throwExceptionIfClosed();
-        return mWidth;
-    }
-
-    @Override
-    public int getImageFormat() {
-        throwExceptionIfClosed();
-        return mFormat;
-    }
-
-    @Override
-    public int getMaxImages() {
-        throwExceptionIfClosed();
-        return mMaxImages;
-    }
-
-    @NonNull
-    @Override
-    public synchronized Surface getSurface() {
-        throwExceptionIfClosed();
-        return mSurface;
-    }
-
-    @Override
-    public synchronized void setOnImageAvailableListener(
-            @NonNull OnImageAvailableListener onImageAvailableListener,
-            @NonNull Executor executor) {
-        throwExceptionIfClosed();
-        mOnImageAvailableListener = onImageAvailableListener;
-        mOnImageAvailableExecutor = executor;
-    }
-
-    @Override
-    public synchronized void clearOnImageAvailableListener() {
-        mOnImageAvailableListener = null;
-        mOnImageAvailableExecutor = null;
-    }
-
-    @Override
-    public synchronized void onImageClose(ImageProxy image) {
-        int index = mImages.indexOf(image);
-        if (index >= 0) {
-            mImages.remove(index);
-            if (index <= mCurrentPosition) {
-                mCurrentPosition--;
-            }
-        }
-        mAcquiredImages.remove(image);
-    }
-
-    /** Returns the current number of images in the queue. */
-    synchronized int getCurrentImages() {
-        throwExceptionIfClosed();
-        return mImages.size();
-    }
-
-    /** Returns true if the reader is already closed. */
-    synchronized boolean isClosed() {
-        return mClosed;
-    }
-
-    /**
-     * Adds a listener for close calls on this reader.
-     *
-     * @param listener to add
-     */
-    synchronized void addOnReaderCloseListener(OnReaderCloseListener listener) {
-        mOnReaderCloseListeners.add(listener);
-    }
-
-    private synchronized void throwExceptionIfClosed() {
-        if (mClosed) {
-            throw new IllegalStateException("This reader is already closed.");
-        }
-    }
-
-    private synchronized void notifyOnReaderCloseListeners() {
-        for (OnReaderCloseListener listener : mOnReaderCloseListeners) {
-            listener.onReaderClose(this);
-        }
-    }
-
-    /** Listener for the reader close event. */
-    interface OnReaderCloseListener {
-        /**
-         * Callback for reader close.
-         *
-         * @param imageReader which is closed
-         */
-        void onReaderClose(ImageReaderProxy imageReader);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ReferenceCountedImageProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/ReferenceCountedImageProxy.java
deleted file mode 100644
index 9388942..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/ReferenceCountedImageProxy.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 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.core;
-
-import android.media.Image;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.Nullable;
-
-/**
- * An {@link ImageProxy} which allows forking images with reference counting.
- *
- * <p>When a new instance is constructed, it starts with a reference count of 1. When {@link
- * #fork()} is called, the reference count increments by 1. When {@link #close()} is called on a
- * forked image reference, the reference count decrements by 1. When the reference count reaches 0
- * after a call to {@link #close()}, the underlying {@link Image} is closed.
- */
-final class ReferenceCountedImageProxy extends ForwardingImageProxy {
-    @GuardedBy("this")
-    private int mReferenceCount = 1;
-
-    /**
-     * Creates a new instance which wraps the given image and sets the reference count to 1.
-     *
-     * @param image to wrap
-     * @return a new {@link ReferenceCountedImageProxy} instance
-     */
-    ReferenceCountedImageProxy(ImageProxy image) {
-        super(image);
-    }
-
-    /**
-     * Forks a copy of the image.
-     *
-     * <p>If the reference count is 0, meaning the image has already been closed previously, null is
-     * returned. Otherwise, a forked copy is returned and the reference count is incremented.
-     */
-    @Nullable
-    synchronized ImageProxy fork() {
-        if (mReferenceCount <= 0) {
-            return null;
-        } else {
-            mReferenceCount++;
-            return new SingleCloseImageProxy(this);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>When the image is closed, the reference count is decremented. If the reference count
-     * becomes 0 after this close call, the underlying {@link Image} is also closed.
-     */
-    @Override
-    public synchronized void close() {
-        if (mReferenceCount > 0) {
-            mReferenceCount--;
-            if (mReferenceCount <= 0) {
-                super.close();
-            }
-        }
-    }
-
-    /** Returns the current reference count. */
-    synchronized int getReferenceCount() {
-        return mReferenceCount;
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index 3533600..7bff94e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -103,7 +103,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Nullable
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         return null;
     }
 
@@ -147,7 +147,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    protected UseCaseConfig<?> applyDefaults(
+    public UseCaseConfig<?> applyDefaults(
             @NonNull UseCaseConfig<?> userConfig,
             @Nullable UseCaseConfig.Builder<?, ?, ?> defaultConfigBuilder) {
         if (defaultConfigBuilder == null) {
@@ -427,7 +427,7 @@
      * @hide
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected void onAttach(@NonNull CameraInternal camera) {
+    public void onAttach(@NonNull CameraInternal camera) {
         synchronized (mCameraLock) {
             mCamera = camera;
             addStateChangeCallback(camera);
@@ -446,7 +446,7 @@
      * @hide
      */
     @RestrictTo(Scope.LIBRARY)
-    public void onDetach() {
+    public void onDetach(@NonNull CameraInternal camera) {
         // Do any cleanup required by the UseCase implementation
         clear();
 
@@ -457,11 +457,10 @@
         }
 
         synchronized (mCameraLock) {
-            if (mCamera != null) {
-                mCamera.detachUseCases(Collections.singleton(this));
-                removeStateChangeCallback(mCamera);
-                mCamera = null;
-            }
+            Preconditions.checkArgument(camera == mCamera);
+            mCamera.detachUseCases(Collections.singleton(this));
+            removeStateChangeCallback(mCamera);
+            mCamera = null;
         }
     }
 
@@ -504,8 +503,8 @@
      *
      * @hide
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    protected void setViewPortCropRect(@Nullable Rect viewPortCropRect) {
+    @RestrictTo(Scope.LIBRARY)
+    public void setViewPortCropRect(@Nullable Rect viewPortCropRect) {
         mViewPortCropRect = viewPortCropRect;
     }
 
@@ -514,8 +513,9 @@
      *
      * @hide
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
+    @RestrictTo(Scope.LIBRARY)
     @Nullable
+    @SuppressWarnings("KotlinPropertyAccess")
     protected Rect getViewPortCropRect() {
         return mViewPortCropRect;
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
index c4bd236..eea0f13 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
@@ -204,7 +204,7 @@
     @Override
     @Nullable
     @RestrictTo(Scope.LIBRARY_GROUP)
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         VideoCaptureConfig defaults = CameraX.getDefaultUseCaseConfig(VideoCaptureConfig.class,
                 cameraInfo);
         if (defaults != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseAttachState.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseAttachState.java
index 4a69b2c..14bbda1 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseAttachState.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseAttachState.java
@@ -19,8 +19,6 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
-import androidx.camera.core.UseCase;
-import androidx.core.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -44,7 +42,7 @@
     /** The name of the camera the use cases are attached to. */
     private final String mCameraId;
     /** A map of the use cases to the corresponding state information. */
-    private final Map<UseCase, UseCaseAttachInfo> mAttachedUseCasesToInfoMap = new HashMap<>();
+    private final Map<String, UseCaseAttachInfo> mAttachedUseCasesToInfoMap = new HashMap<>();
 
     /** Constructs an instance of the attach state which corresponds to the named camera. */
     public UseCaseAttachState(@NonNull String cameraId) {
@@ -56,8 +54,10 @@
      *
      * <p>Adds the use case to the collection if not already in it.
      */
-    public void setUseCaseActive(@NonNull UseCase useCase) {
-        UseCaseAttachInfo useCaseAttachInfo = getOrCreateUseCaseAttachInfo(useCase);
+    public void setUseCaseActive(@NonNull String useCaseName,
+            @NonNull SessionConfig sessionConfig) {
+        UseCaseAttachInfo useCaseAttachInfo = getOrCreateUseCaseAttachInfo(useCaseName,
+                sessionConfig);
         useCaseAttachInfo.setActive(true);
     }
 
@@ -66,15 +66,15 @@
      *
      * <p>Removes the use case from the collection if also offline.
      */
-    public void setUseCaseInactive(@NonNull UseCase useCase) {
-        if (!mAttachedUseCasesToInfoMap.containsKey(useCase)) {
+    public void setUseCaseInactive(@NonNull String useCaseName) {
+        if (!mAttachedUseCasesToInfoMap.containsKey(useCaseName)) {
             return;
         }
 
-        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCase);
+        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCaseName);
         useCaseAttachInfo.setActive(false);
         if (!useCaseAttachInfo.getAttached()) {
-            mAttachedUseCasesToInfoMap.remove(useCase);
+            mAttachedUseCasesToInfoMap.remove(useCaseName);
         }
     }
 
@@ -83,8 +83,10 @@
      *
      * <p>Adds the use case to the collection if not already in it.
      */
-    public void setUseCaseAttached(@NonNull UseCase useCase) {
-        UseCaseAttachInfo useCaseAttachInfo = getOrCreateUseCaseAttachInfo(useCase);
+    public void setUseCaseAttached(@NonNull String useCaseName,
+            @NonNull SessionConfig sessionConfig) {
+        UseCaseAttachInfo useCaseAttachInfo = getOrCreateUseCaseAttachInfo(useCaseName,
+                sessionConfig);
         useCaseAttachInfo.setAttached(true);
     }
 
@@ -93,49 +95,38 @@
      *
      * <p>Removes the use case from the collection if also inactive.
      */
-    public void setUseCaseDetached(@NonNull UseCase useCase) {
-        if (!mAttachedUseCasesToInfoMap.containsKey(useCase)) {
+    public void setUseCaseDetached(@NonNull String useCaseName) {
+        if (!mAttachedUseCasesToInfoMap.containsKey(useCaseName)) {
             return;
         }
-        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCase);
+        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCaseName);
         useCaseAttachInfo.setAttached(false);
         if (!useCaseAttachInfo.getActive()) {
-            mAttachedUseCasesToInfoMap.remove(useCase);
+            mAttachedUseCasesToInfoMap.remove(useCaseName);
         }
     }
 
     /** Returns if the use case is attached or not. */
-    public boolean isUseCaseAttached(@NonNull UseCase useCase) {
-        if (!mAttachedUseCasesToInfoMap.containsKey(useCase)) {
+    public boolean isUseCaseAttached(@NonNull String useCaseName) {
+        if (!mAttachedUseCasesToInfoMap.containsKey(useCaseName)) {
             return false;
         }
 
-        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCase);
+        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCaseName);
         return useCaseAttachInfo.getAttached();
     }
 
     @NonNull
-    public Collection<UseCase> getAttachedUseCases() {
+    public Collection<SessionConfig> getAttachedSessionConfigs() {
         return Collections.unmodifiableCollection(
-                getUseCases(new AttachStateFilter() {
-                    @Override
-                    public boolean filter(UseCaseAttachInfo useCaseAttachInfo) {
-                        return useCaseAttachInfo.getAttached();
-                    }
-                }));
+                getSessionConfigs((useCaseAttachInfo) -> useCaseAttachInfo.getAttached()));
     }
 
     @NonNull
-    public Collection<UseCase> getActiveAndAttachedUseCases() {
+    public Collection<SessionConfig> getActiveAndAttachedSessionConfigs() {
         return Collections.unmodifiableCollection(
-                getUseCases(
-                        new AttachStateFilter() {
-                            @Override
-                            public boolean filter(UseCaseAttachInfo useCaseAttachInfo) {
-                                return useCaseAttachInfo.getActive()
-                                        && useCaseAttachInfo.getAttached();
-                            }
-                        }));
+                getSessionConfigs((useCaseAttachInfo) ->
+                        useCaseAttachInfo.getActive() && useCaseAttachInfo.getAttached()));
     }
 
     /**
@@ -143,20 +134,20 @@
      *
      * <p>If the use case is not already in the collection, nothing is done.
      */
-    public void updateUseCase(@NonNull UseCase useCase) {
-        if (!mAttachedUseCasesToInfoMap.containsKey(useCase)) {
+    public void updateUseCase(@NonNull String useCaseName, @NonNull SessionConfig sessionConfig) {
+        if (!mAttachedUseCasesToInfoMap.containsKey(useCaseName)) {
             return;
         }
 
         // Rebuild the attach info from scratch to get the updated SessionConfig.
         UseCaseAttachInfo newUseCaseAttachInfo =
-                new UseCaseAttachInfo(useCase.getSessionConfig());
+                new UseCaseAttachInfo(sessionConfig);
 
         // Retain the attached and active flags.
-        UseCaseAttachInfo oldUseCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCase);
+        UseCaseAttachInfo oldUseCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCaseName);
         newUseCaseAttachInfo.setAttached(oldUseCaseAttachInfo.getAttached());
         newUseCaseAttachInfo.setActive(oldUseCaseAttachInfo.getActive());
-        mAttachedUseCasesToInfoMap.put(useCase, newUseCaseAttachInfo);
+        mAttachedUseCasesToInfoMap.put(useCaseName, newUseCaseAttachInfo);
     }
 
     /** Returns a session configuration builder for use cases which are both active and attached. */
@@ -165,13 +156,13 @@
         SessionConfig.ValidatingBuilder validatingBuilder = new SessionConfig.ValidatingBuilder();
 
         List<String> list = new ArrayList<>();
-        for (Entry<UseCase, UseCaseAttachInfo> attachedUseCase :
+        for (Entry<String, UseCaseAttachInfo> attachedUseCase :
                 mAttachedUseCasesToInfoMap.entrySet()) {
             UseCaseAttachInfo useCaseAttachInfo = attachedUseCase.getValue();
             if (useCaseAttachInfo.getActive() && useCaseAttachInfo.getAttached()) {
-                UseCase useCase = attachedUseCase.getKey();
+                String useCaseName = attachedUseCase.getKey();
                 validatingBuilder.add(useCaseAttachInfo.getSessionConfig());
-                list.add(useCase.getName());
+                list.add(useCaseName);
             }
         }
         Log.d(TAG, "Active and attached use case: " + list + " for camera: " + mCameraId);
@@ -183,51 +174,38 @@
     public SessionConfig.ValidatingBuilder getAttachedBuilder() {
         SessionConfig.ValidatingBuilder validatingBuilder = new SessionConfig.ValidatingBuilder();
         List<String> list = new ArrayList<>();
-        for (Entry<UseCase, UseCaseAttachInfo> attachedUseCase :
+        for (Entry<String, UseCaseAttachInfo> attachedUseCase :
                 mAttachedUseCasesToInfoMap.entrySet()) {
             UseCaseAttachInfo useCaseAttachInfo = attachedUseCase.getValue();
             if (useCaseAttachInfo.getAttached()) {
                 validatingBuilder.add(useCaseAttachInfo.getSessionConfig());
-                UseCase useCase = attachedUseCase.getKey();
-                list.add(useCase.getName());
+                String useCaseName = attachedUseCase.getKey();
+                list.add(useCaseName);
             }
         }
         Log.d(TAG, "All use case: " + list + " for camera: " + mCameraId);
         return validatingBuilder;
     }
 
-
-    /** Returns current attached SessionConfig of given UseCase */
-    @NonNull
-    public SessionConfig getUseCaseSessionConfig(@NonNull UseCase useCase) {
-        if (!mAttachedUseCasesToInfoMap.containsKey(useCase)) {
-            return SessionConfig.defaultEmptySessionConfig();
-        }
-
-        UseCaseAttachInfo attachInfo = mAttachedUseCasesToInfoMap.get(useCase);
-        return attachInfo.getSessionConfig();
-    }
-
-    private UseCaseAttachInfo getOrCreateUseCaseAttachInfo(UseCase useCase) {
-        Preconditions.checkArgument(
-                useCase.getCamera().getCameraInfoInternal().getCameraId().equals(mCameraId));
-        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCase);
+    private UseCaseAttachInfo getOrCreateUseCaseAttachInfo(@NonNull String useCaseName,
+            @NonNull SessionConfig sessionConfig) {
+        UseCaseAttachInfo useCaseAttachInfo = mAttachedUseCasesToInfoMap.get(useCaseName);
         if (useCaseAttachInfo == null) {
-            useCaseAttachInfo = new UseCaseAttachInfo(useCase.getSessionConfig());
-            mAttachedUseCasesToInfoMap.put(useCase, useCaseAttachInfo);
+            useCaseAttachInfo = new UseCaseAttachInfo(sessionConfig);
+            mAttachedUseCasesToInfoMap.put(useCaseName, useCaseAttachInfo);
         }
         return useCaseAttachInfo;
     }
 
-    private Collection<UseCase> getUseCases(AttachStateFilter attachStateFilter) {
-        List<UseCase> useCases = new ArrayList<>();
-        for (Entry<UseCase, UseCaseAttachInfo> attachedUseCase :
+    private Collection<SessionConfig> getSessionConfigs(AttachStateFilter attachStateFilter) {
+        List<SessionConfig> sessionConfigs = new ArrayList<>();
+        for (Entry<String, UseCaseAttachInfo> attachedUseCase :
                 mAttachedUseCasesToInfoMap.entrySet()) {
             if (attachStateFilter == null || attachStateFilter.filter(attachedUseCase.getValue())) {
-                useCases.add(attachedUseCase.getKey());
+                sessionConfigs.add(attachedUseCase.getValue().getSessionConfig());
             }
         }
-        return useCases;
+        return sessionConfigs;
     }
 
     private interface AttachStateFilter {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
index 980c390..4703e74 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
@@ -131,7 +131,7 @@
 
         for (UseCase useCase : useCasesToClear) {
             Log.d(TAG, "Destroying use case: " + useCase.getName());
-            useCase.onDetach();
+            useCase.onDetach(useCase.getCamera());
             useCase.onDestroy();
         }
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
new file mode 100644
index 0000000..1346c52
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -0,0 +1,259 @@
+/*
+ * 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.camera.core.internal;
+
+import android.graphics.Rect;
+import android.util.Log;
+import android.util.Size;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.camera.core.UseCase;
+import androidx.camera.core.ViewPort;
+import androidx.camera.core.impl.CameraControlInternal;
+import androidx.camera.core.impl.CameraDeviceSurfaceManager;
+import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.impl.SurfaceConfig;
+import androidx.camera.core.impl.UseCaseConfig;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A {@link CameraInternal} adapter which checks that the UseCases to make sure that the resolutions
+ * and image formats can be supported.
+ */
+public final class CameraUseCaseAdapter {
+    private final CameraInternal mCameraInternal;
+    private final CameraDeviceSurfaceManager mCameraDeviceSurfaceManager;
+
+    private static final String TAG = "CameraUseCaseAdapter";
+
+    @GuardedBy("mLock")
+    private final List<UseCase> mAttachedUseCases = new ArrayList<>();
+
+    @GuardedBy("mLock")
+    @Nullable
+    private ViewPort mViewPort;
+
+    private final Object mLock = new Object();
+
+    /**
+     * Create a new {@link CameraUseCaseAdapter} instance.
+     *
+     * @param cameraInternal the actual camera implementation that is wrapped
+     * @param cameraDeviceSurfaceManager A class that checks for whether a specific camera
+     *                                   can support the set of Surface with set resolutions.
+     */
+    public CameraUseCaseAdapter(@NonNull CameraInternal cameraInternal,
+            @NonNull CameraDeviceSurfaceManager cameraDeviceSurfaceManager) {
+        mCameraInternal = cameraInternal;
+        mCameraDeviceSurfaceManager = cameraDeviceSurfaceManager;
+    }
+
+    /**
+     * Set the viewport that will be used for the {@link UseCase} attached to the camera.
+     */
+    public void setViewPort(@Nullable ViewPort viewPort) {
+        synchronized (mLock) {
+            mViewPort = viewPort;
+        }
+    }
+
+    /**
+     * Check to see if the set of {@link UseCase} can be attached to the camera.
+     *
+     * <p> This does not take into account UseCases which are already attached to the camera.
+     *
+     * @throws CameraException
+     */
+    public void checkAttachUseCases(@NonNull List<UseCase> useCases) throws CameraException {
+        // Only do resolution calculation if UseCases were bound
+        if (!UseCaseOccupancy.checkUseCaseLimitNotExceeded(useCases)) {
+            throw new CameraException("Attempting to bind too many ImageCapture or "
+                    + "VideoCapture instances");
+        }
+
+        // If the UseCases exceed the resolutions then it will throw an exception
+        try {
+            calculateSuggestedResolutions(useCases, Collections.emptyList());
+        } catch (IllegalArgumentException e) {
+            throw new CameraException(e.getMessage());
+        }
+    }
+
+    /**
+     * Attach the specified collection of {@link UseCase} to the camera.
+     *
+     * @throws CameraException Thrown if the combination of newly attached UseCases and the
+     * currently attached UseCases exceed the capability of the camera.
+     */
+    public void attachUseCases(@NonNull Collection<UseCase> useCases) throws CameraException {
+        synchronized (mLock) {
+            List<UseCase> useCaseListAfterUpdate = new ArrayList<>(mAttachedUseCases);
+            List<UseCase> newUseCases = new ArrayList<>();
+
+            for (UseCase useCase : useCases) {
+                if (mAttachedUseCases.contains(useCase)) {
+                    Log.e(TAG, "Attempting to attach already attached UseCase");
+                } else {
+                    useCaseListAfterUpdate.add(useCase);
+                    newUseCases.add(useCase);
+                }
+            }
+
+            // Only do resolution calculation if UseCases were bound
+            if (!UseCaseOccupancy.checkUseCaseLimitNotExceeded(useCaseListAfterUpdate)) {
+                throw new CameraException("Attempting to bind too many ImageCapture or "
+                        + "VideoCapture instances");
+            }
+
+            Map<UseCase, Size> suggestedResolutionsMap;
+            try {
+                suggestedResolutionsMap =
+                        calculateSuggestedResolutions(newUseCases, mAttachedUseCases);
+            }  catch (IllegalArgumentException e) {
+                throw new CameraException(e.getMessage());
+            }
+
+            if (mViewPort != null) {
+                // Calculate crop rect if view port is provided.
+                Map<UseCase, Rect> cropRectMap = ViewPorts.calculateViewPortRects(
+                        mCameraInternal.getCameraControlInternal().getSensorRect(),
+                        mViewPort.getAspectRatio(),
+                        mCameraInternal.getCameraInfoInternal().getSensorRotationDegrees(
+                                mViewPort.getRotation()),
+                        mViewPort.getScaleType(),
+                        mViewPort.getLayoutDirection(),
+                        suggestedResolutionsMap);
+                for (UseCase useCase : useCases) {
+                    useCase.setViewPortCropRect(cropRectMap.get(useCase));
+                }
+            }
+
+            // At this point the binding will succeed since all the calculations are done
+            // Do all attaching related work
+            for (UseCase useCase : newUseCases) {
+                useCase.onAttach(mCameraInternal);
+                useCase.updateSuggestedResolution(suggestedResolutionsMap.get(useCase));
+            }
+
+            mAttachedUseCases.addAll(newUseCases);
+            mCameraInternal.attachUseCases(newUseCases);
+        }
+    }
+
+    /**
+     * Detached the specified collection of {@link UseCase} from the camera.
+     */
+    public void detachUseCases(@NonNull Collection<UseCase> useCases) {
+        synchronized (mLock) {
+            mCameraInternal.detachUseCases(useCases);
+
+            for (UseCase useCase : useCases) {
+                if (mAttachedUseCases.contains(useCase)) {
+                    useCase.onDetach(mCameraInternal);
+                    useCase.onDestroy();
+                } else {
+                    Log.e(TAG, "Attempting to detach non-attached UseCase: " + useCase);
+                }
+            }
+
+            mAttachedUseCases.removeAll(useCases);
+        }
+    }
+
+    private Map<UseCase, Size> calculateSuggestedResolutions(@NonNull List<UseCase> newUseCases,
+            @NonNull List<UseCase> currentUseCases) {
+        List<SurfaceConfig> existingSurfaces = new ArrayList<>();
+        String cameraId = mCameraInternal.getCameraInfoInternal().getCameraId();
+
+        Map<UseCaseConfig<?>, UseCase> configToUseCaseMap = new HashMap<>();
+
+        for (UseCase useCase : currentUseCases) {
+            SurfaceConfig surfaceConfig =
+                    mCameraDeviceSurfaceManager.transformSurfaceConfig(cameraId,
+                            useCase.getImageFormat(),
+                            useCase.getAttachedSurfaceResolution());
+            existingSurfaces.add(surfaceConfig);
+        }
+
+        for (UseCase useCase : newUseCases) {
+            UseCaseConfig.Builder<?, ?, ?> defaultBuilder = useCase.getDefaultBuilder(
+                    mCameraInternal.getCameraInfoInternal());
+
+            // Combine with default configuration.
+            UseCaseConfig<?> combinedUseCaseConfig =
+                    useCase.applyDefaults(useCase.getUseCaseConfig(),
+                            defaultBuilder);
+            configToUseCaseMap.put(combinedUseCaseConfig, useCase);
+        }
+
+        // Get suggested resolutions and update the use case session configuration
+        Map<UseCaseConfig<?>, Size> useCaseConfigSizeMap = mCameraDeviceSurfaceManager
+                .getSuggestedResolutions(cameraId, existingSurfaces,
+                        new ArrayList<>(configToUseCaseMap.keySet()));
+
+        Map<UseCase, Size> suggestedResolutions = new HashMap<>();
+        for (Map.Entry<UseCaseConfig<?>, UseCase> entry : configToUseCaseMap.entrySet()) {
+            suggestedResolutions.put(entry.getValue(), useCaseConfigSizeMap.get(entry.getKey()));
+        }
+
+        return suggestedResolutions;
+    }
+
+    /**
+     * Get the {@link CameraInternal} instance that is wrapped by this {@link CameraUseCaseAdapter}.
+     */
+    @NonNull
+    public CameraInternal getCameraInternal() {
+        return mCameraInternal;
+    }
+
+    @NonNull
+    public CameraInfoInternal getCameraInfoInternal() {
+        return mCameraInternal.getCameraInfoInternal();
+    }
+
+    @NonNull
+    public CameraControlInternal getCameraControlInternal() {
+        return mCameraInternal.getCameraControlInternal();
+    }
+
+    /**
+     * An exception thrown when the {@link CameraUseCaseAdapter} errors in one of its operations.
+     */
+    public static final class CameraException extends Exception {
+        public CameraException() {
+            super();
+        }
+
+        public CameraException(@NonNull String message) {
+            super(message);
+        }
+
+        public CameraException(@NonNull Throwable cause) {
+            super(cause);
+        }
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseOccupancy.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseOccupancy.java
index 73bc504..57b9b8b 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseOccupancy.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseOccupancy.java
@@ -36,25 +36,14 @@
     /**
      * Check to see if CameraX supports running the set of use cases.
      *
-     * @param originalUseCases  the currently existing use cases
-     * @param newUseCases       the use cases to be added
      * @return true if the set of use cases is supported, otherwise false
      */
     public static boolean checkUseCaseLimitNotExceeded(
-            @NonNull List<UseCase> originalUseCases,
-            @NonNull List<UseCase> newUseCases) {
+            @NonNull List<UseCase> useCases) {
         int imageCaptureCount = 0;
         int videoCaptureCount = 0;
 
-        for (UseCase useCase : originalUseCases) {
-            if (useCase instanceof ImageCapture) {
-                imageCaptureCount++;
-            } else if (useCase instanceof VideoCapture) {
-                videoCaptureCount++;
-            }
-        }
-
-        for (UseCase useCase : newUseCases) {
+        for (UseCase useCase : useCases) {
             if (useCase instanceof ImageCapture) {
                 imageCaptureCount++;
             } else if (useCase instanceof VideoCapture) {
diff --git a/camera/camera-testing/build.gradle b/camera/camera-testing/build.gradle
index 133a93f..ee9ec74 100644
--- a/camera/camera-testing/build.gradle
+++ b/camera/camera-testing/build.gradle
@@ -25,7 +25,7 @@
 }
 
 dependencies {
-    implementation(ANDROIDX_TEST_CORE)
+    implementation("androidx.test:core:1.2.0")
     implementation(ANDROIDX_TEST_UIAUTOMATOR)
     api("androidx.annotation:annotation:1.0.0")
     implementation(GUAVA_LISTENABLE_FUTURE)
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
index 8229ea4..0640d95 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
@@ -192,7 +192,8 @@
     public void onUseCaseActive(@NonNull UseCase useCase) {
         Log.d(TAG, "Use case " + useCase + " ACTIVE for camera " + mCameraId);
 
-        mUseCaseAttachState.setUseCaseActive(useCase);
+        mUseCaseAttachState.setUseCaseActive(useCase.getName() + useCase.hashCode(),
+                useCase.getSessionConfig());
         updateCaptureSessionConfig();
     }
 
@@ -201,7 +202,7 @@
     public void onUseCaseInactive(@NonNull UseCase useCase) {
         Log.d(TAG, "Use case " + useCase + " INACTIVE for camera " + mCameraId);
 
-        mUseCaseAttachState.setUseCaseInactive(useCase);
+        mUseCaseAttachState.setUseCaseInactive(useCase.getName() + useCase.hashCode());
         updateCaptureSessionConfig();
     }
 
@@ -210,7 +211,8 @@
     public void onUseCaseUpdated(@NonNull UseCase useCase) {
         Log.d(TAG, "Use case " + useCase + " UPDATED for camera " + mCameraId);
 
-        mUseCaseAttachState.updateUseCase(useCase);
+        mUseCaseAttachState.updateUseCase(useCase.getName() + useCase.hashCode(),
+                useCase.getSessionConfig());
         updateCaptureSessionConfig();
     }
 
@@ -218,7 +220,8 @@
     public void onUseCaseReset(@NonNull UseCase useCase) {
         Log.d(TAG, "Use case " + useCase + " RESET for camera " + mCameraId);
 
-        mUseCaseAttachState.updateUseCase(useCase);
+        mUseCaseAttachState.updateUseCase(useCase.getName() + useCase.hashCode(),
+                useCase.getSessionConfig());
         updateCaptureSessionConfig();
         openCaptureSession();
     }
@@ -235,7 +238,8 @@
 
         Log.d(TAG, "Use cases " + useCases + " ATTACHED for camera " + mCameraId);
         for (UseCase useCase : useCases) {
-            mUseCaseAttachState.setUseCaseAttached(useCase);
+            mUseCaseAttachState.setUseCaseAttached(useCase.getName() + useCase.hashCode(),
+                    useCase.getSessionConfig());
         }
 
         open();
@@ -255,10 +259,10 @@
 
         Log.d(TAG, "Use cases " + useCases + " DETACHED for camera " + mCameraId);
         for (UseCase useCase : useCases) {
-            mUseCaseAttachState.setUseCaseDetached(useCase);
+            mUseCaseAttachState.setUseCaseDetached(useCase.getName() + useCase.hashCode());
         }
 
-        if (mUseCaseAttachState.getAttachedUseCases().isEmpty()) {
+        if (mUseCaseAttachState.getAttachedSessionConfigs().isEmpty()) {
             close();
             return;
         }
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
index 76c414d..df25e3a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
@@ -47,7 +47,7 @@
 
     @Override
     @Nullable
-    protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+    public UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
         return new FakeUseCaseConfig.Builder()
                 .setSessionOptionUnpacker(new SessionConfig.OptionUnpacker() {
                     @Override
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewBitmapTest.java b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewBitmapTest.java
index 1b661ca..dac3379 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewBitmapTest.java
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewBitmapTest.java
@@ -125,7 +125,7 @@
     }
 
     @Test
-    public void bitmapNotNull_whenPreviewIsDisplaying_surfaceViewView() throws Throwable {
+    public void bitmapNotNull_whenPreviewIsDisplaying_surfaceView() throws Throwable {
         // Arrange
         final PreviewView previewView = setUpPreviewView(ImplementationMode.SURFACE_VIEW);
 
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewStreamStateTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewStreamStateTest.kt
index 793273d..adfe64c 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewStreamStateTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewStreamStateTest.kt
@@ -34,7 +34,6 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.test.rule.GrantPermissionRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
@@ -66,8 +65,9 @@
     @get:Rule
     var mCameraPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.CAMERA)
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var mActivityRule = ActivityTestRule(
+    var mActivityRule = androidx.test.rule.ActivityTestRule(
         FakeActivity::class.java
     )
 
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
index 4e1f2dd..8aae806 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
@@ -46,6 +46,8 @@
 import androidx.annotation.Nullable;
 import androidx.camera.core.CameraInfo;
 import androidx.camera.core.CameraSelector;
+import androidx.camera.core.MeteringPoint;
+import androidx.camera.core.MeteringPointFactory;
 import androidx.camera.core.Preview;
 import androidx.camera.core.SurfaceRequest;
 import androidx.camera.core.impl.CameraInfoInternal;
@@ -209,10 +211,58 @@
         assertThat(previewView.mImplementation).isInstanceOf(TextureViewImplementation.class);
     }
 
-    @Test(expected = NullPointerException.class)
-    public void throwsException_whenCreatingMeteringPointFactory_beforeCreatingSurfaceProvider() {
+    @Test
+    @UiThreadTest
+    public void canCreateMeteringPointFactory() {
+        final CameraInfo cameraInfo = createCameraInfo(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2);
+
         final PreviewView previewView = new PreviewView(mContext);
-        previewView.createMeteringPointFactory(CameraSelector.DEFAULT_BACK_CAMERA);
+        setContentView(previewView);
+
+        Preview.SurfaceProvider surfaceProvider = previewView.createSurfaceProvider();
+        mSurfaceRequest = createSurfaceRequest(cameraInfo);
+        surfaceProvider.onSurfaceRequested(mSurfaceRequest);
+        MeteringPointFactory factory =
+                previewView.createMeteringPointFactory(CameraSelector.DEFAULT_BACK_CAMERA);
+
+        MeteringPoint point = factory.createPoint(100, 100);
+        assertThat(point.getX() >= 0f || point.getX() <= 1.0f);
+        assertThat(point.getY() >= 0f || point.getY() <= 1.0f);
+    }
+
+    @Test
+    @UiThreadTest
+    public void createMeteringPointFactory_previewViewWidthOrHeightIs0() {
+        final CameraInfo cameraInfo = createCameraInfo(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2);
+
+        final PreviewView previewView = new PreviewView(mContext);
+        Preview.SurfaceProvider surfaceProvider = previewView.createSurfaceProvider();
+        mSurfaceRequest = createSurfaceRequest(cameraInfo);
+        surfaceProvider.onSurfaceRequested(mSurfaceRequest);
+
+        MeteringPointFactory factory =
+                previewView.createMeteringPointFactory(CameraSelector.DEFAULT_BACK_CAMERA);
+
+        //Width and height is 0,  but surface is requested,
+        //verifying the factory only creates invalid points.
+        MeteringPoint point = factory.createPoint(100, 100);
+        assertThat(point.getX() < 0f || point.getX() > 1.0f);
+        assertThat(point.getY() < 0f || point.getY() > 1.0f);
+    }
+
+    @Test
+    @UiThreadTest
+    public void createMeteringPointFactory_beforeCreatingSurfaceProvider() {
+        final PreviewView previewView = new PreviewView(mContext);
+        // make PreviewView.getWidth() getHeight not 0.
+        setContentView(previewView);
+        MeteringPointFactory factory =
+                previewView.createMeteringPointFactory(CameraSelector.DEFAULT_BACK_CAMERA);
+
+        //verifying the factory only creates invalid points.
+        MeteringPoint point = factory.createPoint(100, 100);
+        assertThat(point.getX() < 0f || point.getX() > 1.0f);
+        assertThat(point.getY() < 0f || point.getY() > 1.0f);
     }
 
     @Test
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
index 52c20f5..5c61e2e 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -53,8 +52,9 @@
     private lateinit var mSurfaceRequest: SurfaceRequest
 
     // Shows the view in activity so that SurfaceView can work normally
+    @Suppress("DEPRECATION")
     @get:Rule
-    var mActivityRule = ActivityTestRule(
+    var mActivityRule = androidx.test.rule.ActivityTestRule(
         FakeActivity::class.java
     )
 
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 8f54a6a..9281f56 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -37,6 +37,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraInfo;
 import androidx.camera.core.CameraSelector;
+import androidx.camera.core.FocusMeteringAction;
 import androidx.camera.core.MeteringPoint;
 import androidx.camera.core.MeteringPointFactory;
 import androidx.camera.core.Preview;
@@ -45,7 +46,6 @@
 import androidx.camera.core.impl.utils.Threads;
 import androidx.camera.view.preview.transform.PreviewTransform;
 import androidx.core.content.ContextCompat;
-import androidx.core.util.Preconditions;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 
@@ -218,7 +218,7 @@
             camera.getCameraState().addObserver(
                     ContextCompat.getMainExecutor(getContext()), streamStateObserver);
 
-            mImplementation.onSurfaceRequested(surfaceRequest, ()-> {
+            mImplementation.onSurfaceRequested(surfaceRequest, () -> {
                 // We've no longer needed this observer, if there is no new StreamStateObserver
                 // (another SurfaceRequest), reset the streamState to IDLE.
                 // This is needed for the case when unbinding preview while other use cases are
@@ -308,20 +308,26 @@
 
     /**
      * Creates a {@link MeteringPointFactory} by a given {@link CameraSelector}
-     * <p>
-     * This {@link MeteringPointFactory} is capable of creating a {@link MeteringPoint} by a
-     * (x, y) in the {@link PreviewView}. It converts the points by current scaleType.
+     *
+     * <p>The returned {@link MeteringPointFactory} is capable of creating {@link MeteringPoint}s
+     * from (x, y) coordinates in the {@link PreviewView}. This conversion takes into account its
+     * {@link ScaleType}. It is recommended to call this method to create a new factory every
+     * time you start a focus and metering action, instead of caching the factory instance.
+     *
+     * <p>When the PreviewView has a width and/or height equal to zero, or when a preview
+     * {@link Surface} is not yet requested, the returned factory will always create invalid
+     * {@link MeteringPoint}s which could lead to the failure of
+     * {@link androidx.camera.core.CameraControl#startFocusAndMetering(FocusMeteringAction)} but it
+     * won't cause any crash.
      *
      * @param cameraSelector the CameraSelector which the {@link Preview} is bound to.
      * @return a {@link MeteringPointFactory}
      */
     @NonNull
     public MeteringPointFactory createMeteringPointFactory(@NonNull CameraSelector cameraSelector) {
-        Preconditions.checkNotNull(mImplementation,
-                "Must set the Preview's surfaceProvider and bind it to a lifecycle first");
         return new PreviewViewMeteringPointFactory(getDisplay(), cameraSelector,
-                mImplementation.getResolution(), mPreviewTransform.getScaleType(), getWidth(),
-                getHeight());
+                mImplementation == null ? null : mImplementation.getResolution(),
+                mPreviewTransform.getScaleType(), getWidth(), getHeight());
     }
 
     /**
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/SurfaceViewImplementation.java b/camera/camera-view/src/main/java/androidx/camera/view/SurfaceViewImplementation.java
index 2f55dd3..2669257 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/SurfaceViewImplementation.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/SurfaceViewImplementation.java
@@ -167,10 +167,14 @@
          */
         @UiThread
         void setSurfaceRequest(@NonNull SurfaceRequest surfaceRequest) {
+            // Cancel the previous request, if any
             cancelPreviousRequest();
+
             mSurfaceRequest = surfaceRequest;
             Size targetSize = surfaceRequest.getResolution();
             mTargetSize = targetSize;
+            mWasSurfaceProvided = false;
+
             if (!tryToComplete()) {
                 // The current size is incorrect. Wait for it to change.
                 Log.d(TAG, "Wait for new Surface creation.");
@@ -186,7 +190,7 @@
          */
         @UiThread
         private boolean tryToComplete() {
-            Surface surface = mSurfaceView.getHolder().getSurface();
+            final Surface surface = mSurfaceView.getHolder().getSurface();
             if (canProvideSurface()) {
                 Log.d(TAG, "Surface set on Preview.");
                 mSurfaceRequest.provideSurface(surface,
@@ -203,7 +207,7 @@
         }
 
         private boolean canProvideSurface() {
-            return mSurfaceRequest != null && mTargetSize != null
+            return !mWasSurfaceProvided && mSurfaceRequest != null && mTargetSize != null
                     && mTargetSize.equals(mCurrentSurfaceSize);
         }
 
@@ -239,11 +243,17 @@
         @Override
         public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
             Log.d(TAG, "Surface destroyed.");
+
+            // If a surface was already provided to the camera, invalidate it so that it requests
+            // a new valid one. Otherwise, cancel the surface request.
             if (mWasSurfaceProvided) {
                 invalidateSurface();
             } else {
                 cancelPreviousRequest();
             }
+
+            // Reset state
+            mWasSurfaceProvided = false;
             mSurfaceRequest = null;
             mCurrentSurfaceSize = null;
             mTargetSize = null;
diff --git a/camera/integration-tests/coretestapp/build.gradle b/camera/integration-tests/coretestapp/build.gradle
index 5b9711c..7f6c5cd 100644
--- a/camera/integration-tests/coretestapp/build.gradle
+++ b/camera/integration-tests/coretestapp/build.gradle
@@ -108,5 +108,7 @@
     androidTestImplementation(project(":concurrent:concurrent-futures-ktx"))
     androidTestImplementation(project(':internal-testutils-runtime'))
 
+    testImplementation(JUNIT)
+    testImplementation(TRUTH)
 }
 
diff --git a/camera/integration-tests/coretestapp/src/main/AndroidManifest.xml b/camera/integration-tests/coretestapp/src/main/AndroidManifest.xml
index 1544355..c8d6045 100644
--- a/camera/integration-tests/coretestapp/src/main/AndroidManifest.xml
+++ b/camera/integration-tests/coretestapp/src/main/AndroidManifest.xml
@@ -31,6 +31,16 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".OpenGLActivity"
+            android:label="Camera Core Test App (OpenGL Activity)"
+            android:theme="@style/NoTitleTheme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
     </application>
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
index 64e5e46..edd2a32 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
@@ -81,7 +81,6 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.Locale;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -137,31 +136,6 @@
     @ImageCapture.CaptureMode
     private int mCaptureMode = ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY;
 
-    /**
-     * Intent Extra string for choosing which type of render surface to use to display Preview.
-     */
-    public static final String INTENT_EXTRA_RENDER_SURFACE_TYPE = "render_surface_type";
-    /**
-     * TextureView render surface for {@link #INTENT_EXTRA_RENDER_SURFACE_TYPE}. This is the
-     * default render surface.
-     */
-    public static final String RENDER_SURFACE_TYPE_TEXTUREVIEW = "textureview";
-    /**
-     * SurfaceView render surface for {@link #INTENT_EXTRA_RENDER_SURFACE_TYPE}. This type will
-     * block the main thread while detaching it's {@link android.view.Surface} from the OpenGL
-     * renderer to avoid compatibility issues on some devices.
-     */
-    public static final String RENDER_SURFACE_TYPE_SURFACEVIEW = "surfaceview";
-    /**
-     * SurfaceView render surface (in non-blocking mode) for
-     * {@link #INTENT_EXTRA_RENDER_SURFACE_TYPE}. This type will NOT
-     * block the main thread while detaching it's {@link android.view.Surface} from the OpenGL
-     * renderer, but some devices may crash due to their OpenGL/EGL implementation not being
-     * thread-safe.
-     */
-    public static final String RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING =
-            "surfaceview_nonblocking";
-
     private OpenGLRenderer mPreviewRenderer;
     private DisplayManager.DisplayListener mDisplayListener;
 
@@ -655,43 +629,14 @@
         createVideoCapture();
     }
 
-    private View chooseViewFinder(@NonNull ViewStub viewFinderStub,
-            @NonNull OpenGLRenderer renderer) {
-        Bundle bundle = getIntent().getExtras();
-        // By default we choose TextureView to maximize compatibility.
-        String renderSurfaceType = RENDER_SURFACE_TYPE_TEXTUREVIEW;
-        if (bundle != null) {
-            renderSurfaceType = bundle.getString(INTENT_EXTRA_RENDER_SURFACE_TYPE,
-                    RENDER_SURFACE_TYPE_TEXTUREVIEW);
-        }
-
-        switch (renderSurfaceType) {
-            case RENDER_SURFACE_TYPE_TEXTUREVIEW:
-                Log.d(TAG, "Using TextureView render surface.");
-                return TextureViewRenderSurface.inflateWith(viewFinderStub, renderer);
-            case RENDER_SURFACE_TYPE_SURFACEVIEW:
-                Log.d(TAG, "Using SurfaceView render surface.");
-                return SurfaceViewRenderSurface.inflateWith(viewFinderStub, renderer);
-            case RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING:
-                Log.d(TAG, "Using SurfaceView (non-blocking) render surface.");
-                return SurfaceViewRenderSurface.inflateNonBlockingWith(viewFinderStub, renderer);
-            default:
-                throw new IllegalArgumentException(String.format(Locale.US, "Unknown render "
-                        + "surface type: %s. Supported surface types include: [%s, %s, %s]",
-                        renderSurfaceType, RENDER_SURFACE_TYPE_TEXTUREVIEW,
-                        RENDER_SURFACE_TYPE_SURFACEVIEW,
-                        RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING));
-        }
-    }
-
-    @SuppressWarnings("UnstableApiUsage")
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_camera_xmain);
         OpenGLRenderer previewRenderer = mPreviewRenderer = new OpenGLRenderer();
         ViewStub viewFinderStub = findViewById(R.id.viewFinderStub);
-        View viewFinder = chooseViewFinder(viewFinderStub, previewRenderer);
+        View viewFinder = OpenGLActivity.chooseViewFinder(getIntent().getExtras(), viewFinderStub,
+                previewRenderer);
 
         mDisplayListener = new DisplayManager.DisplayListener() {
             @Override
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/FpsRecorder.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/FpsRecorder.java
new file mode 100644
index 0000000..01898e33
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/FpsRecorder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.camera.integration.core;
+
+import androidx.annotation.IntRange;
+
+final class FpsRecorder {
+    private static final double NANOS_IN_SECOND = 1_000_000_000;
+    private final long[] mTimestamps;
+    private int mIndex = 0;
+    private int mNumSamples = 0; // Number of samples used in calculation.
+
+    /**
+     * Creates an fps recorder that creates a running average of {@code bufferLength+1} samples.
+     */
+    FpsRecorder(@IntRange(from = 1) int bufferLength) {
+        if (bufferLength < 1) {
+            throw new IllegalArgumentException("Invalid buffer length. Buffer must contain at "
+                    + "least 1 sample");
+        }
+        mTimestamps = new long[bufferLength];
+    }
+
+    /**
+     * Records the latest timestamp and returns the latest fps value or NaN if not enough samples
+     * have been recorded.
+     */
+    double recordTimestamp(long timestampNs) {
+        // Find the duration between the oldest and newest timestamp
+        int nextIndex = (mIndex + 1) % mTimestamps.length;
+        long duration = timestampNs - mTimestamps[mIndex];
+        mTimestamps[mIndex] = timestampNs;
+        mIndex = nextIndex;
+        // The discarded sample is used in the calculation, so we use a maximum of bufferLength +
+        // 1 samples.
+        mNumSamples = Math.min(mNumSamples + 1, mTimestamps.length + 1);
+
+        if (mNumSamples == mTimestamps.length + 1) {
+            return (NANOS_IN_SECOND * mTimestamps.length) / duration;
+        }
+
+        // Return NaN if we don't have enough samples
+        return Double.NaN;
+    }
+
+    /**
+     * Ignores all previously recorded timestamps and calculates timestamps from new recorded
+     * timestamps.
+     *
+     * <p>{@link #recordTimestamp(long)} will return NaN until enough samples have been
+     * recorded.
+     */
+    void reset() {
+        mNumSamples = 0;
+        mIndex = 0;
+    }
+}
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLActivity.java
new file mode 100644
index 0000000..9d58518
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLActivity.java
@@ -0,0 +1,264 @@
+/*
+ * 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.camera.integration.core;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewStub;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.AspectRatio;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+
+/** Activity which runs the camera preview with opengl processing */
+public class OpenGLActivity extends AppCompatActivity {
+    private static final String TAG = "OpenGLActivity";
+
+    /**
+     * Intent Extra string for choosing which type of render surface to use to display Preview.
+     */
+    public static final String INTENT_EXTRA_RENDER_SURFACE_TYPE = "render_surface_type";
+    /**
+     * TextureView render surface for {@link OpenGLActivity#INTENT_EXTRA_RENDER_SURFACE_TYPE}.
+     * This is the default render surface.
+     */
+    public static final String RENDER_SURFACE_TYPE_TEXTUREVIEW = "textureview";
+    /**
+     * SurfaceView render surface for {@link OpenGLActivity#INTENT_EXTRA_RENDER_SURFACE_TYPE}.
+     * This type will block the main thread while detaching it's {@link Surface} from the OpenGL
+     * renderer to avoid compatibility issues on some devices.
+     */
+    public static final String RENDER_SURFACE_TYPE_SURFACEVIEW = "surfaceview";
+    /**
+     * SurfaceView render surface (in non-blocking mode) for
+     * {@link OpenGLActivity#INTENT_EXTRA_RENDER_SURFACE_TYPE}. This type will NOT
+     * block the main thread while detaching it's {@link Surface} from the OpenGL
+     * renderer, but some devices may crash due to their OpenGL/EGL implementation not being
+     * thread-safe.
+     */
+    public static final String RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING =
+            "surfaceview_nonblocking";
+    private static final String[] REQUIRED_PERMISSIONS =
+            new String[]{
+                    Manifest.permission.CAMERA,
+            };
+
+    private static final int FPS_NUM_SAMPLES = 10;
+    private OpenGLRenderer mRenderer;
+    private DisplayManager.DisplayListener mDisplayListener;
+    private ProcessCameraProvider mCameraProvider;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.opengl_activity);
+
+        OpenGLRenderer renderer = mRenderer = new OpenGLRenderer();
+        ViewStub viewFinderStub = findViewById(R.id.viewFinderStub);
+        View viewFinder = OpenGLActivity.chooseViewFinder(getIntent().getExtras(), viewFinderStub,
+                renderer);
+
+        // Add a frame update listener to display FPS
+        FpsRecorder fpsRecorder = new FpsRecorder(FPS_NUM_SAMPLES);
+        TextView fpsCounterView = findViewById(R.id.fps_counter);
+        renderer.setFrameUpdateListener(ContextCompat.getMainExecutor(this), timestamp -> {
+            double fps = fpsRecorder.recordTimestamp(timestamp);
+            fpsCounterView.setText(getString(R.string.fps_counter_template,
+                    (Double.isNaN(fps) || Double.isInfinite(fps)) ? "---" : String.format(Locale.US,
+                            "%.0f", fps)));
+        });
+
+        // A display listener is needed when the phone rotates 180 degrees without stopping at a
+        // 90 degree increment. In these cases, onCreate() isn't triggered, so we need to ensure
+        // the output surface uses the correct orientation.
+        mDisplayListener =
+                new DisplayListener() {
+                    @Override
+                    public void onDisplayAdded(int displayId) {
+                    }
+
+                    @Override
+                    public void onDisplayRemoved(int displayId) {
+                    }
+
+                    @Override
+                    public void onDisplayChanged(int displayId) {
+                        Display viewFinderDisplay = viewFinder.getDisplay();
+                        if (viewFinderDisplay != null
+                                && viewFinderDisplay.getDisplayId() == displayId) {
+                            renderer.invalidateSurface(Surfaces.toSurfaceRotationDegrees(
+                                    viewFinderDisplay.getRotation()));
+                        }
+                    }
+                };
+
+        DisplayManager dpyMgr =
+                Objects.requireNonNull((DisplayManager) getSystemService(Context.DISPLAY_SERVICE));
+        dpyMgr.registerDisplayListener(mDisplayListener, new Handler(Looper.getMainLooper()));
+
+        CameraXViewModel viewModel = new ViewModelProvider(this).get(CameraXViewModel.class);
+        viewModel
+                .getCameraProvider()
+                .observe(
+                        this,
+                        cameraProviderResult -> {
+                            if (cameraProviderResult.hasProvider()) {
+                                mCameraProvider = cameraProviderResult.getProvider();
+                                if (allPermissionsGranted()) {
+                                    startCamera();
+                                }
+                            } else {
+                                Log.e(TAG, "Failed to retrieve ProcessCameraProvider",
+                                        cameraProviderResult.getError());
+                                Toast.makeText(getApplicationContext(),
+                                        "Unable to initialize CameraX. See logs "
+                                                + "for details.", Toast.LENGTH_LONG).show();
+                            }
+                        });
+
+        if (!allPermissionsGranted()) {
+            mRequestPermissions.launch(REQUIRED_PERMISSIONS);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        DisplayManager dpyMgr = Objects.requireNonNull(
+                (DisplayManager) getSystemService(Context.DISPLAY_SERVICE));
+        dpyMgr.unregisterDisplayListener(mDisplayListener);
+        mRenderer.shutdown();
+    }
+
+    /**
+     * Chooses the type of view to use for the viewfinder based on intent extras.
+     *
+     * @param intentExtras   Optional extras which can contain an extra with key
+     *                       {@link #INTENT_EXTRA_RENDER_SURFACE_TYPE}. Possible values are one of
+     *                       {@link #RENDER_SURFACE_TYPE_TEXTUREVIEW},
+     *                       {@link #RENDER_SURFACE_TYPE_SURFACEVIEW}, or
+     *                       {@link #RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING}. If {@code null},
+     *                       or the bundle does not contain a surface type, then
+     *                       {@link #RENDER_SURFACE_TYPE_TEXTUREVIEW} will be used.
+     * @param viewFinderStub The stub to inflate the chosen viewfinder into.
+     * @param renderer       The {@link OpenGLRenderer} which will render frames into the
+     *                       viewfinder.
+     * @return The inflated viewfinder View.
+     */
+    public static View chooseViewFinder(@Nullable Bundle intentExtras,
+            @NonNull ViewStub viewFinderStub,
+            @NonNull OpenGLRenderer renderer) {
+        // By default we choose TextureView to maximize compatibility.
+        String renderSurfaceType = OpenGLActivity.RENDER_SURFACE_TYPE_TEXTUREVIEW;
+        if (intentExtras != null) {
+            renderSurfaceType = intentExtras.getString(INTENT_EXTRA_RENDER_SURFACE_TYPE,
+                    RENDER_SURFACE_TYPE_TEXTUREVIEW);
+        }
+
+        switch (renderSurfaceType) {
+            case RENDER_SURFACE_TYPE_TEXTUREVIEW:
+                Log.d(TAG, "Using TextureView render surface.");
+                return TextureViewRenderSurface.inflateWith(viewFinderStub, renderer);
+            case RENDER_SURFACE_TYPE_SURFACEVIEW:
+                Log.d(TAG, "Using SurfaceView render surface.");
+                return SurfaceViewRenderSurface.inflateWith(viewFinderStub, renderer);
+            case RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING:
+                Log.d(TAG, "Using SurfaceView (non-blocking) render surface.");
+                return SurfaceViewRenderSurface.inflateNonBlockingWith(viewFinderStub, renderer);
+            default:
+                throw new IllegalArgumentException(String.format(Locale.US, "Unknown render "
+                                + "surface type: %s. Supported surface types include: [%s, %s, %s]",
+                        renderSurfaceType, RENDER_SURFACE_TYPE_TEXTUREVIEW,
+                        RENDER_SURFACE_TYPE_SURFACEVIEW,
+                        RENDER_SURFACE_TYPE_SURFACEVIEW_NONBLOCKING));
+        }
+    }
+
+    private void startCamera() {
+        // Keep screen on for this app. This is just for convenience, and is not required.
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        // Set the aspect ratio of Preview to match the aspect ratio of the view finder (defined
+        // with ConstraintLayout).
+        Preview preview = new Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build();
+
+        mRenderer.attachInputPreview(preview);
+
+        CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
+
+        mCameraProvider.bindToLifecycle(this, cameraSelector, preview);
+    }
+
+    // **************************** Permission handling code start *******************************//
+    private final ActivityResultLauncher<String[]> mRequestPermissions =
+            registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
+                    new ActivityResultCallback<Map<String, Boolean>>() {
+                        @Override
+                        public void onActivityResult(Map<String, Boolean> result) {
+                            for (String permission : REQUIRED_PERMISSIONS) {
+                                if (!Objects.requireNonNull(result.get(permission))) {
+                                    Toast.makeText(OpenGLActivity.this, "Permissions not granted",
+                                            Toast.LENGTH_SHORT).show();
+                                    finish();
+                                }
+                            }
+
+                            // All permissions granted.
+                            if (mCameraProvider != null) {
+                                startCamera();
+                            }
+                        }
+                    });
+
+    private boolean allPermissionsGranted() {
+        for (String permission : REQUIRED_PERMISSIONS) {
+            if (ContextCompat.checkSelfPermission(this, permission)
+                    != PackageManager.PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return true;
+    }
+    // **************************** Permission handling code end *********************************//
+}
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLRenderer.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLRenderer.java
index 372e864..f90473b 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLRenderer.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLRenderer.java
@@ -206,6 +206,7 @@
     @WorkerThread
     private void doShutdownIfNeeded() {
         if (mIsShutdown && mNumOutstandingSurfaces == 0) {
+            mFrameUpdateListener = null;
             mExecutor.shutdown();
         }
     }
@@ -245,9 +246,9 @@
                     mPreviewTransform);
             if (success && mFrameUpdateListener != null) {
                 Executor executor = mFrameUpdateListener.first;
+                Consumer<Long> listener = mFrameUpdateListener.second;
                 try {
                     executor.execute(() -> {
-                        Consumer<Long> listener = mFrameUpdateListener.second;
                         listener.accept(timestampNs);
                     });
                 } catch (RejectedExecutionException e) {
diff --git a/camera/integration-tests/coretestapp/src/main/res/layout-land/opengl_activity.xml b/camera/integration-tests/coretestapp/src/main/res/layout-land/opengl_activity.xml
new file mode 100644
index 0000000..e80d0c3
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/main/res/layout-land/opengl_activity.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ViewStub
+        android:id="@+id/viewFinderStub"
+        android:inflatedId="@id/viewFinder"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintDimensionRatio="W, 4:3"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <TextView
+        android:id="@+id/fps_counter"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="18dp"
+        android:layout_marginEnd="18dp"
+        android:text="--- fps"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/main/res/layout/opengl_activity.xml b/camera/integration-tests/coretestapp/src/main/res/layout/opengl_activity.xml
new file mode 100644
index 0000000..a9cf1b8
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/main/res/layout/opengl_activity.xml
@@ -0,0 +1,46 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ViewStub
+        android:id="@+id/viewFinderStub"
+        android:inflatedId="@id/viewFinder"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintDimensionRatio="H, 3:4"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <TextView
+        android:id="@+id/fps_counter"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="18dp"
+        android:layout_marginEnd="18dp"
+        android:text="--- fps"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/main/res/values/strings.xml b/camera/integration-tests/coretestapp/src/main/res/values/strings.xml
new file mode 100644
index 0000000..9a038a1
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/main/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?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.
+  -->
+
+<resources>
+    <string name="fps_counter_template">%1$s fps</string>
+</resources>
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/main/res/values/style.xml b/camera/integration-tests/coretestapp/src/main/res/values/style.xml
index 7503cc0..c1d6296f 100644
--- a/camera/integration-tests/coretestapp/src/main/res/values/style.xml
+++ b/camera/integration-tests/coretestapp/src/main/res/values/style.xml
@@ -15,7 +15,10 @@
 -->
 <resources>
     <!-- Base application theme. -->
-    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
-        <!-- Customize your theme here. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" />
+    <!-- No title bar theme. -->
+    <style name="NoTitleTheme" parent="Theme.AppCompat.NoActionBar">
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:windowContentOverlay">@null</item>
     </style>
 </resources>
diff --git a/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/FpsRecorderTest.java b/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/FpsRecorderTest.java
new file mode 100644
index 0000000..ecd9909
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/test/java/androidx/camera/integration/core/FpsRecorderTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.camera.integration.core;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import androidx.annotation.NonNull;
+
+import com.google.common.truth.StandardSubjectBuilder;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+
+@RunWith(JUnit4.class)
+public class FpsRecorderTest {
+
+    private static final int TEST_FPS = 30;
+    private static final long TEST_FPS_DURATION_NANOS = 1_000_000_000L / TEST_FPS;
+    private static final long TIMESTAMP_BASE_NANOS = 1234567654321L;
+    private static final double FPS_ALLOWED_ERROR = 1e-4;
+
+    @Test
+    public void fpsIsCalculated_withSingleSampleBuffer() {
+        FpsRecorder fpsRecorder = new FpsRecorder(1);
+        fpsRecorder.recordTimestamp(TIMESTAMP_BASE_NANOS);
+        double fps = fpsRecorder.recordTimestamp(TIMESTAMP_BASE_NANOS + TEST_FPS_DURATION_NANOS);
+        assertThat(fps).isWithin(FPS_ALLOWED_ERROR).of(TEST_FPS);
+    }
+
+    @Test
+    public void fpsIsNaN_untilBufferSizePlusOneSamples() {
+        double[] expected = {Double.NaN, Double.NaN, Double.NaN, Double.NaN, TEST_FPS};
+        double[] actual = new double[expected.length];
+
+        FpsRecorder fpsRecorder = new FpsRecorder(expected.length - 1);
+        long timestamp = TIMESTAMP_BASE_NANOS;
+        for (int i = 0; i < expected.length; ++i) {
+            actual[i] = fpsRecorder.recordTimestamp(timestamp);
+            timestamp += TEST_FPS_DURATION_NANOS;
+        }
+
+        // Cannot compare with withTolerance() since NaN is not considered equal to itself in
+        // that case
+        for (int i = 0; i < actual.length; ++i) {
+            if (Double.isFinite(actual[i])) {
+                assertThat(actual[i]).isWithin(FPS_ALLOWED_ERROR).of(expected[i]);
+            } else {
+                assertThat(actual[i]).isEqualTo(expected[i]);
+            }
+        }
+
+        assertElementsWithinTolerance_ignoringNaN(actual, expected);
+    }
+
+    @Test
+    public void fpsIsNaN_afterReset() {
+        double[] expected =
+                {Double.NaN, Double.NaN, Double.NaN, TEST_FPS, Double.NaN, Double.NaN, Double.NaN,
+                        TEST_FPS};
+        double[] actual = new double[expected.length];
+
+        FpsRecorder fpsRecorder = new FpsRecorder(expected.length / 2 - 1);
+        long timestamp = TIMESTAMP_BASE_NANOS;
+        for (int i = 0; i < expected.length; ++i) {
+            if (i == expected.length / 2) {
+                fpsRecorder.reset();
+            }
+
+            actual[i] = fpsRecorder.recordTimestamp(timestamp);
+            timestamp += TEST_FPS_DURATION_NANOS;
+        }
+
+        assertElementsWithinTolerance_ignoringNaN(actual, expected);
+    }
+
+    @Test
+    public void fpsIsCalculated_withLargeBuffer() {
+        int bufferSize = 100;
+        FpsRecorder fpsRecorder = new FpsRecorder(bufferSize);
+        long timeStamp = TIMESTAMP_BASE_NANOS;
+        double fpsOut = Double.NaN;
+        for (int i = 0; i < bufferSize + 1; ++i) {
+            fpsOut = fpsRecorder.recordTimestamp(timeStamp);
+            timeStamp += TEST_FPS_DURATION_NANOS;
+        }
+
+        assertThat(fpsOut).isWithin(FPS_ALLOWED_ERROR).of(TEST_FPS);
+    }
+
+    @Test
+    public void skippedFrame_dropsFps() {
+        int bufferSize = 4;
+        FpsRecorder fpsRecorder = new FpsRecorder(bufferSize);
+        long timeStamp = TIMESTAMP_BASE_NANOS;
+        double fpsOut = Double.NaN;
+        for (int i = 0; i < bufferSize + 1; ++i) {
+            fpsOut = fpsRecorder.recordTimestamp(timeStamp);
+            timeStamp += TEST_FPS_DURATION_NANOS;
+            if (i == 1) {
+                // Simulate dropped frame. Add additional duration to timestamp.
+                timeStamp += TEST_FPS_DURATION_NANOS;
+            }
+        }
+
+        assertThat(fpsOut).isNotWithin(FPS_ALLOWED_ERROR).of(TEST_FPS);
+        assertThat(fpsOut).isLessThan(TEST_FPS);
+    }
+
+    private void assertElementsWithinTolerance_ignoringNaN(@NonNull double[] actual,
+            @NonNull double[] expected) {
+        // Cannot compare with withTolerance() since NaN is not considered equal to itself in
+        // that case
+        for (int i = 0; i < actual.length; ++i) {
+            StandardSubjectBuilder assertWithMessage = assertWithMessage(
+                    "Assumption violation while "
+                            + "comparing actual: [%s] to expected: [%s] at position %s",
+                    Arrays.toString(actual),
+                    Arrays.toString(expected),
+                    Integer.toString(i));
+            if (Double.isFinite(actual[i])) {
+                assertWithMessage.that(actual[i]).isWithin(FPS_ALLOWED_ERROR).of(expected[i]);
+            } else {
+                assertWithMessage.that(actual[i]).isEqualTo(expected[i]);
+            }
+        }
+    }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/build.gradle b/camera/integration-tests/uiwidgetstestapp/build.gradle
index 6c39233..e1a8506 100644
--- a/camera/integration-tests/uiwidgetstestapp/build.gradle
+++ b/camera/integration-tests/uiwidgetstestapp/build.gradle
@@ -71,5 +71,6 @@
     androidTestImplementation(ESPRESSO_CORE)
     androidTestImplementation(project(":camera:camera-testing"))
     androidTestImplementation(TRUTH)
+    debugImplementation(ANDROIDX_TEST_CORE)
     debugImplementation("androidx.fragment:fragment-testing:1.2.3")
 }
\ No newline at end of file
diff --git a/camera/integration-tests/viewtestapp/build.gradle b/camera/integration-tests/viewtestapp/build.gradle
index 1811866..6d13fe4 100644
--- a/camera/integration-tests/viewtestapp/build.gradle
+++ b/camera/integration-tests/viewtestapp/build.gradle
@@ -70,6 +70,7 @@
     androidTestImplementation(ESPRESSO_CORE)
     androidTestImplementation(project(":camera:camera-testing"))
     androidTestImplementation(TRUTH)
+    debugImplementation(ANDROIDX_TEST_CORE)
     debugImplementation("androidx.fragment:fragment-testing:1.2.3")
 }
 
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
index 0baeab2..b4f6822 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
@@ -86,11 +86,90 @@
     }
 
     @Test
+    fun testPrimitiveChangedCalls(): Unit = validateBytecode(
+        """
+        @Composable fun Foo(
+            a: Boolean,
+            b: Char,
+            c: Byte,
+            d: Short,
+            e: Int,
+            f: Float,
+            g: Long,
+            h: Double
+        ) {}
+        """
+    ) {
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (Z)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (C)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (B)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (S)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (I)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (F)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (J)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (D)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (Ljava/lang/Object;)Z"))
+    }
+
+    @Test
+    fun testNonPrimitiveChangedCalls(): Unit = validateBytecode(
+        """
+        import androidx.compose.Stable
+
+        @Stable class Bar
+        @Composable fun Foo(a: Bar) {}
+        """
+    ) {
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (Z)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (C)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (B)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (S)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (I)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (F)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (J)Z"))
+        assert(!it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (D)Z"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (Ljava/lang/Object;)Z"))
+    }
+
+    @Test
+    fun testInlineClassChangedCalls(): Unit = validateBytecode(
+        """
+        inline class Bar(val value: Int)
+        @Composable fun Foo(a: Bar) {}
+        """
+    ) {
+        assert(!it.contains("INVOKESTATIC Bar.box-impl (I)LBar;"))
+        assert(it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (I)Z"))
+        assert(
+            !it.contains("INVOKEVIRTUAL androidx/compose/Composer.changed (Ljava/lang/Object;)Z")
+        )
+    }
+
+    @Test
+    fun testNullableInlineClassChangedCalls(): Unit = validateBytecode(
+        """
+        inline class Bar(val value: Int)
+        @Composable fun Foo(a: Bar?) {}
+        """
+    ) {
+        val testClass = it.split("public final class ").single { it.startsWith("TestKt") }
+        assert(!testClass.contains(
+            "INVOKEVIRTUAL Bar.unbox-impl ()I"
+        ))
+        assert(!testClass.contains(
+            "INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;"
+        ))
+        assert(testClass.contains(
+            "INVOKEVIRTUAL androidx/compose/Composer.changed (Ljava/lang/Object;)Z"
+        ))
+    }
+
+    @Test
     fun testNoNullCheckForPassedParameters(): Unit = validateBytecode(
         """
         inline class Bar(val value: Int)
         fun nonNull(bar: Bar) {}
-        @Direct @Composable fun Foo(bar: Bar = Bar(123)) {
+        @ComposableContract(restartable = false) @Composable fun Foo(bar: Bar = Bar(123)) {
             nonNull(bar)
         }
         """
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
index f5e8a44..73ab333 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
@@ -26,7 +26,7 @@
     ) = verifyComposeIrTransform(
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
 
             $source
         """.trimIndent(),
@@ -40,7 +40,7 @@
         """
             @Composable val bar: Int get() { return 123 }
 
-            @Direct @Composable fun Example() {
+            @ComposableContract(restartable = false) @Composable fun Example() {
                 bar
             }
         """,
@@ -52,7 +52,7 @@
                 %composer.endReplaceableGroup()
                 return tmp0
               }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -66,25 +66,25 @@
     fun testAbstractComposable(): Unit = composerParam(
         """
             abstract class BaseFoo {
-                @Direct
+                @ComposableContract(restartable = false)
                 @Composable
                 abstract fun bar()
             }
 
             class FooImpl : BaseFoo() {
-                @Direct
+                @ComposableContract(restartable = false)
                 @Composable
                 override fun bar() {}
             }
         """,
         """
             abstract class BaseFoo {
-              @Direct
+              @ComposableContract(restartable = false)
               @Composable
               abstract fun bar(%composer: Composer<*>?, %key: Int, %changed: Int)
             }
             class FooImpl : BaseFoo {
-              @Direct
+              @ComposableContract(restartable = false)
               @Composable
               override fun bar(%composer: Composer<*>?, %key: Int, %changed: Int) {
                 %composer.startReplaceableGroup(%key)
@@ -97,18 +97,18 @@
     @Test
     fun testLocalClassAndObjectLiterals(): Unit = composerParam(
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Wat() {}
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Foo(x: Int) {
                 Wat()
-                @Direct
+                @ComposableContract(restartable = false)
                 @Composable fun goo() { Wat() }
                 class Bar {
-                    @Direct
+                    @ComposableContract(restartable = false)
                     @Composable fun baz() { Wat() }
                 }
                 goo()
@@ -116,18 +116,18 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Wat(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
               %composer.endReplaceableGroup()
             }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Foo(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
               Wat(%composer, <>, 0)
-              @Direct
+              @ComposableContract(restartable = false)
               @Composable
               fun goo(%composer: Composer<*>?, %key: Int, %changed: Int) {
                 %composer.startReplaceableGroup(%key)
@@ -135,7 +135,7 @@
                 %composer.endReplaceableGroup()
               }
               class Bar {
-                @Direct
+                @ComposableContract(restartable = false)
                 @Composable
                 fun baz(%composer: Composer<*>?, %key: Int, %changed: Int) {
                   %composer.startReplaceableGroup(%key)
@@ -212,13 +212,13 @@
     @Test
     fun testCircularCall(): Unit = composerParam(
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable fun Example() {
                 Example()
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -235,7 +235,7 @@
                 children()
             }
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable fun Test() {
                 Example {}
             }
@@ -247,7 +247,7 @@
               children(%composer, <>, 0b0110 and %changed)
               %composer.endReplaceableGroup()
             }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Test(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -270,7 +270,7 @@
 
             private fun TextView.setRef(ref: (TextView) -> Unit) {}
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Test() {
                 TextView(ref = {  })
@@ -278,7 +278,7 @@
         """,
         """
             private fun TextView.setRef(ref: Function1<TextView, Unit>) { }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Test(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -286,7 +286,7 @@
                 { it: TextView ->
                 }
               }, %composer, <>, 0)
-              %composer.emit(-1248659145, { context: @[ParameterName(name = 'context')] Context ->
+              %composer.emit(-1248659174, { context: @[ParameterName(name = 'context')] Context ->
                 TextView(context)
               }
               ) {
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ControlFlowTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ControlFlowTransformTests.kt
index 4e98ec6..021599b 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ControlFlowTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ControlFlowTransformTests.kt
@@ -27,7 +27,7 @@
         """
             import androidx.compose.Composable
             import androidx.compose.key
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
 
             $source
         """.trimIndent(),
@@ -51,7 +51,7 @@
     @Test
     fun testIfNonComposable(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // No composable calls, so no group generated except for at function boundary
                 if (x > 0) {
@@ -60,7 +60,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -75,7 +75,7 @@
     @Test
     fun testIfWithCallsInBranch(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // Composable calls in the result blocks, so we can determine static number of
                 // groups executed. This means we put a group around the "then" and the implicit
@@ -86,7 +86,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -106,7 +106,7 @@
     @Test
     fun testIfElseWithCallsInBranch(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // Composable calls in the result blocks, so we can determine static number of
                 // groups executed. This means we put a group around the "then" and the
@@ -119,7 +119,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -140,7 +140,7 @@
     @Test
     fun testIfWithCallInCondition(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // Since the first condition of an if/else is unconditionally executed, it does not
                 // necessitate a group of any kind, so we just end up with the function boundary
@@ -153,7 +153,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -170,7 +170,7 @@
     @Test
     fun testIfElseWithCallsInConditions(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // Since the condition in the else-if is conditionally executed, it means we have
                 // dynamic execution and we can't statically guarantee the number of groups. As a
@@ -187,7 +187,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -212,7 +212,7 @@
     @Test
     fun testWhenWithSubjectAndNoCalls(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // nothing needed except for the function boundary group
                 when (x) {
@@ -223,7 +223,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -247,7 +247,7 @@
     @Test
     fun testWhenWithSubjectAndCalls(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // calls only in the result block, which means we can statically guarantee the
                 // number of groups, so no group around the when is needed, just groups around the
@@ -260,7 +260,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -290,7 +290,7 @@
     @Test
     fun testWhenWithSubjectAndCallsWithResult(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // no need for a group around the when expression overall, but since the result
                 // of the expression is now being used, we need to generate temporary variables to
@@ -303,7 +303,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -336,7 +336,7 @@
     @Test
     fun testWhenWithCalls(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // result blocks have composable calls, so we generate groups round them. It's a
                 // statically guaranteed number of groups at execution, so no wrapping group is
@@ -349,7 +349,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -378,7 +378,7 @@
     @Test
     fun testWhenWithCallsInSomeResults(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // result blocks have composable calls, so we generate groups round them. It's a
                 // statically guaranteed number of groups at execution, so no wrapping group is
@@ -391,7 +391,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -420,7 +420,7 @@
     @Test
     fun testWhenWithCallsInConditions(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // composable calls are in the condition blocks of the when statement. Since these
                 // are conditionally executed, we can't statically know the number of groups during
@@ -434,13 +434,13 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
               when {
                 %composer.startReplaceableGroup(<>)
-                val tmp0_group = x == R(%composer, 0b01110111010101111000000111101001, 0)
+                val tmp0_group = x == R(%composer, 0b01110111010101111000001000010110, 0)
                 %composer.endReplaceableGroup()
                 tmp0_group -> {
                   NA()
@@ -463,7 +463,7 @@
     @Test
     fun testWhenWithCallsInConditionsAndCallAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // composable calls are in the condition blocks of the when statement. Since these
                 // are conditionally executed, we can't statically know the number of groups during
@@ -477,14 +477,14 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
               %composer.startReplaceableGroup(<>)
               when {
                 %composer.startReplaceableGroup(<>)
-                val tmp0_group = x == R(%composer, 0b01110111010101111000000110010001, 0)
+                val tmp0_group = x == R(%composer, 0b01110111010101111000000110111110, 0)
                 %composer.endReplaceableGroup()
                 tmp0_group -> {
                   NA()
@@ -509,7 +509,7 @@
     @Test
     fun testSafeCall(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int?) {
                 // the composable call is made conditionally, which means it is like an if, but one
                 // with static groups, so no wrapping group needed.
@@ -517,7 +517,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int?, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -542,7 +542,7 @@
     @Test
     fun testElvis(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int?) {
                 // the composable call is made conditionally, which means it is like an if, but one
                 // with static groups, so no wrapping group needed.
@@ -550,7 +550,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int?, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -576,7 +576,7 @@
     @Test
     fun testForLoopWithCallsInBody(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: List<Int>) {
                 // The composable call is made a conditional number of times, so we need to wrap
                 // the loop with a dynamic wrapping group. Since there are no other calls, the
@@ -587,7 +587,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: List<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -604,7 +604,7 @@
     @Test
     fun testForLoopWithCallsInBodyAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: List<Int>) {
                 // The composable call is made a conditional number of times, so we need to wrap
                 // the loop with a dynamic wrapping group.
@@ -615,7 +615,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: List<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -635,7 +635,7 @@
     @Test
     fun testForLoopWithCallsInSubject(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example() {
                 // The for loop's subject expression is only executed once, so we don't need any
                 // additional groups
@@ -645,7 +645,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -662,7 +662,7 @@
     @Test
     fun testWhileLoopWithCallsInBody(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: MutableList<Int>) {
                 // since we have a composable call which is called a conditional number of times,
                 // we need to generate groups around the loop's block as well as a group around the
@@ -675,7 +675,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: MutableList<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -691,7 +691,7 @@
     @Test
     fun testWhileLoopWithCallsInBodyAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: MutableList<Int>) {
                 // since we have a composable call which is called a conditional number of times,
                 // we need to generate groups around the loop's block as well as a group around the
@@ -704,7 +704,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: MutableList<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -723,7 +723,7 @@
     @Test
     fun testWhileLoopWithCallsInCondition(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example() {
                 // A while loop's condition block gets executed a conditional number of times, so
                 // so we must generate a group around the while expression overall. The function
@@ -734,7 +734,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -749,7 +749,7 @@
     @Test
     fun testWhileLoopWithCallsInConditionAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example() {
                 // A while loop's condition block gets executed a conditional number of times, so
                 // so we must generate a group around the while expression overall.
@@ -760,7 +760,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -778,7 +778,7 @@
     @Test
     fun testWhileLoopWithCallsInConditionAndBody(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example() {
                 // Both the condition and the body of the loop get groups because they have
                 // composable calls in them. We must generate a group around the while statement
@@ -789,7 +789,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -804,7 +804,7 @@
     @Test
     fun testWhileLoopWithCallsInConditionAndBodyAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example() {
                 // Both the condition and the body of the loop get groups because they have
                 // composable calls in them. We must generate a group around the while statement
@@ -816,7 +816,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -834,7 +834,7 @@
     @Test
     fun testEarlyReturnWithCallsBeforeButNotAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // in the early return path, we need only close out the opened groups
                 if (x > 0) {
@@ -845,7 +845,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -868,7 +868,7 @@
     @Test
     fun testEarlyReturnWithCallsAfterButNotBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 // we can just close out the open groups at the return.
                 if (x > 0) {
@@ -878,7 +878,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -895,7 +895,7 @@
     @Test
     fun testEarlyReturnValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int): Int {
                 if (x > 0) {
                     A()
@@ -905,7 +905,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int): Int {
               %composer.startReplaceableGroup(%key)
@@ -930,7 +930,7 @@
     @Test
     fun testEarlyReturnValueWithCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int): Int {
                 if (x > 0) {
                     return 1
@@ -940,7 +940,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int): Int {
               %composer.startReplaceableGroup(%key)
@@ -960,7 +960,7 @@
     @Test
     fun testReturnCallValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(): Int {
                 // since the return expression is a composable call, we need to generate a
                 // temporary variable and then return it after ending the open groups.
@@ -969,7 +969,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int): Int {
               %composer.startReplaceableGroup(%key)
@@ -984,7 +984,7 @@
     @Test
     fun testEarlyReturnCallValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int): Int {
                 if (x > 0) {
                     return R()
@@ -993,7 +993,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int): Int {
               %composer.startReplaceableGroup(%key)
@@ -1017,7 +1017,7 @@
     @Test
     fun testReturnFromLoop(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1033,7 +1033,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1108,7 +1108,7 @@
     @Test
     fun testBreakWithCallsAfter(): Unit = controlFlow(
             """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1120,7 +1120,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1139,7 +1139,7 @@
     @Test
     fun testBreakWithCallsBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1151,7 +1151,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1170,7 +1170,7 @@
     @Test
     fun testBreakWithCallsBeforeAndAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 // a group around while is needed here, but the function body group will suffice
                 while (items.hasNext()) {
@@ -1184,7 +1184,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1204,7 +1204,7 @@
     @Test
     fun testBreakWithCallsBeforeAndAfterAndCallAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 // a group around while is needed here
                 while (items.hasNext()) {
@@ -1219,7 +1219,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1242,7 +1242,7 @@
     @Test
     fun testContinueWithCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1254,7 +1254,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1273,7 +1273,7 @@
     @Test
     fun testContinueWithCallsBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1286,7 +1286,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1306,7 +1306,7 @@
     @Test
     fun testContinueWithCallsBeforeAndAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(items: Iterator<Int>) {
                 while (items.hasNext()) {
                     val i = items.next()
@@ -1319,7 +1319,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1339,7 +1339,7 @@
     @Test
     fun testLoopWithReturn(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>) {
                 while (a.hasNext()) {
                     val x = a.next()
@@ -1351,7 +1351,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1371,7 +1371,7 @@
     @Test
     fun testLoopWithBreak(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>) {
                 a@while (a.hasNext()) {
                     val x = a.next()
@@ -1387,7 +1387,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1413,7 +1413,7 @@
     @Test
     fun testNestedLoopsAndBreak(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>) {
                 a@while (a.hasNext()) {
                     val x = a.next()
@@ -1438,7 +1438,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1475,7 +1475,7 @@
     @Test
     fun testNestedLoops(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>) {
                 a@while (a.hasNext()) {
                     b@while (b.hasNext()) {
@@ -1487,7 +1487,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1510,7 +1510,7 @@
     @Test
     fun testWhileInsideIfAndCallAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     while (x > 0) {
@@ -1521,7 +1521,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1546,7 +1546,7 @@
     @Test
     fun testWhileInsideIfAndCallBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     A()
@@ -1557,7 +1557,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1580,7 +1580,7 @@
     @Test
     fun testWhileInsideIf(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     while (x > 0) {
@@ -1590,7 +1590,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1612,7 +1612,7 @@
     @Test
     fun testWhileWithKey(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while (x > 0) {
                     key(x) {
@@ -1622,7 +1622,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1639,7 +1639,7 @@
     @Test
     fun testWhileWithTwoKeys(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while (x > 0) {
                     key(x) {
@@ -1652,7 +1652,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1672,7 +1672,7 @@
     @Test
     fun testWhileWithKeyAndCallAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while (x > 0) {
                     key(x) {
@@ -1683,7 +1683,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1701,7 +1701,7 @@
     @Test
     fun testWhileWithKeyAndCallBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while (x > 0) {
                     A()
@@ -1712,7 +1712,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1730,7 +1730,7 @@
     @Test
     fun testWhileWithKeyAndCallBeforeAndAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while (x > 0) {
                     A()
@@ -1742,7 +1742,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1761,7 +1761,7 @@
     @Test
     fun testKeyAtRootLevel(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 key(x) {
                     A()
@@ -1769,7 +1769,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1784,7 +1784,7 @@
     @Test
     fun testKeyAtRootLevelAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 key(x) {
                     A()
@@ -1793,7 +1793,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1809,7 +1809,7 @@
     @Test
     fun testKeyAtRootLevelAndCallsBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 A()
                 key(x) {
@@ -1818,7 +1818,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1834,7 +1834,7 @@
     @Test
     fun testKeyInIf(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     key(x) {
@@ -1844,7 +1844,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1866,7 +1866,7 @@
     @Test
     fun testKeyInIfAndCallsAfter(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     key(x) {
@@ -1877,7 +1877,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1900,7 +1900,7 @@
     @Test
     fun testKeyInIfAndCallsBefore(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 if (x > 0) {
                     A()
@@ -1911,7 +1911,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1934,7 +1934,7 @@
     @Test
     fun testKeyWithLotsOfValues(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(a: Int, b: Int, c: Int, d: Int) {
                 key(a, b, c, d) {
                     A()
@@ -1942,7 +1942,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(a: Int, b: Int, c: Int, d: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1957,7 +1957,7 @@
     @Test
     fun testKeyWithComposableValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 while(x > 0) {
                     key(R()) {
@@ -1967,7 +1967,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -1984,14 +1984,14 @@
     @Test
     fun testKeyAsAValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int) {
                 val y = key(x) { R() }
                 P(y)
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -2009,7 +2009,7 @@
     @Test
     fun testDynamicWrappingGroupWithReturnValue(): Unit = controlFlow(
         """
-            @Direct @Composable
+            @ComposableContract(restartable = false) @Composable
             fun Example(x: Int): Int {
                 return if (x > 0) {
                     if (B()) 1
@@ -2019,7 +2019,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Example(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int): Int {
               %composer.startReplaceableGroup(%key)
@@ -2050,7 +2050,7 @@
     @Test
     fun testTheThing(): Unit = controlFlow(
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Simple() {
               // this has a composable call in it, and since we don't know the number of times the
@@ -2061,7 +2061,7 @@
               A()
             }
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun WithReturn() {
               // this has an early return in it, so it needs to end all of the groups present.
@@ -2072,7 +2072,7 @@
               A()
             }
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun NoCalls() {
               // this has no composable calls in it, so shouldn't cause any groups to get created
@@ -2082,7 +2082,7 @@
               A()
             }
 
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun NoCallsAfter() {
               // this has a composable call in the lambda, but not after it, which means the
@@ -2093,7 +2093,7 @@
             }
         """,
         """
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun Simple(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -2105,7 +2105,7 @@
               A(%composer, <>, 0)
               %composer.endReplaceableGroup()
             }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun WithReturn(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -2120,7 +2120,7 @@
               A(%composer, <>, 0)
               %composer.endReplaceableGroup()
             }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun NoCalls(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
@@ -2130,7 +2130,7 @@
               A(%composer, <>, 0)
               %composer.endReplaceableGroup()
             }
-            @Direct
+            @ComposableContract(restartable = false)
             @Composable
             fun NoCallsAfter(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startReplaceableGroup(%key)
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
index 9c2778c..107e893 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
@@ -27,14 +27,14 @@
     ) = verifyComposeIrTransform(
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
 
             $checked
         """.trimIndent(),
         expectedTransformed,
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
 
             $unchecked
         """.trimIndent(),
@@ -101,7 +101,7 @@
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
               } else if (%changed and 0b0110 === 0) {
-                %dirty = %dirty or if (%composer.changed(foo)) 0b0100 else 0b0010
+                %dirty = %dirty or if (%composer.changed(foo.value)) 0b0100 else 0b0010
               }
               if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                 print(foo)
@@ -1014,17 +1014,17 @@
         """,
         """
             open class Foo {
-                @Direct @Composable fun foo(x: Int = 0) {}
+                @ComposableContract(restartable = false) @Composable fun foo(x: Int = 0) {}
             }
             class Bar: Foo() {
-                @Direct @Composable fun Example() {
+                @ComposableContract(restartable = false) @Composable fun Example() {
                     foo()
                 }
             }
         """,
         """
             open class Foo {
-              @Direct
+              @ComposableContract(restartable = false)
               @Composable
               fun foo(x: Int, %composer: Composer<*>?, %key: Int, %changed: Int, %default: Int) {
                 %composer.startReplaceableGroup(%key)
@@ -1033,7 +1033,7 @@
               }
             }
             class Bar : Foo {
-              @Direct
+              @ComposableContract(restartable = false)
               @Composable
               fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
                 %composer.startReplaceableGroup(%key)
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
index da6232a..cacd00e 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
@@ -40,7 +40,7 @@
     ) = verifyComposeIrTransform(
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
             import android.widget.TextView
             import android.widget.LinearLayout
 
@@ -49,7 +49,7 @@
         expectedTransformed,
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
             import android.widget.TextView
             import android.widget.LinearLayout
 
@@ -106,7 +106,7 @@
                     cond.value = !cond.value
                   }
                 }, %composer, <>, 0)
-                %composer.emit(1124847890, { context: @[ParameterName(name = 'context')] Context ->
+                %composer.emit(1124847878, { context: @[ParameterName(name = 'context')] Context ->
                   Button(context)
                 }
                 ) {
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
index 9962be8..f09ae93 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
@@ -1547,16 +1547,14 @@
 
                 @Composable
                 fun Counter() {
-                    Observe {
-                        var count = state { 0 }
-                        TextView(
-                            text=("Count: " + count.value),
-                            onClick={
-                                count.value += 1
-                            },
-                            id=42
-                        )
-                    }
+                    var count = state { 0 }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
                 }
             """,
             { mapOf<String, String>() },
@@ -1581,16 +1579,14 @@
 
                 @Composable
                 fun Counter() {
-                    Observe {
-                        var count = state { 0 }
-                        TextView(
-                            text=("Count: " + count.value),
-                            onClick={
-                                count.value += 1
-                            },
-                            id=42
-                        )
-                    }
+                    var count = state { 0 }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
                 }
             """,
             { mapOf<String, String>() },
@@ -1616,22 +1612,20 @@
 
                 @Composable
                 fun Counter(log: StringBuilder) {
-                    Observe {
-                        var count = state { 0 }
-                        onCommit {
-                            log.append("a")
-                        }
-                        onActive {
-                            log.append("b")
-                        }
-                        TextView(
-                            text=("Count: " + count.value),
-                            onClick={
-                                count.value += 1
-                            },
-                            id=42
-                        )
+                    var count = state { 0 }
+                    onCommit {
+                        log.append("a")
                     }
+                    onActive {
+                        log.append("b")
+                    }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
                 }
             """,
             { mapOf("log" to log) },
@@ -1668,17 +1662,15 @@
 
                 @Composable
                 fun Counter(log: StringBuilder) {
-                    Observe {
-                        var count = state { 0 }
-                        printer(log, "" + count.value)
-                        TextView(
-                            text=("Count: " + count.value),
-                            onClick={
-                                count.value += 1
-                            },
-                            id=42
-                        )
-                    }
+                    var count = state { 0 }
+                    printer(log, "" + count.value)
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
                 }
             """,
             { mapOf("log" to log) },
@@ -1828,22 +1820,20 @@
 
             @Composable
             fun Reordering() {
-                Observe {
-                    val items = state { listOf(1, 2, 3, 4, 5) }
+                val items = state { listOf(1, 2, 3, 4, 5) }
 
-                    LinearLayout(orientation=LinearLayout.VERTICAL) {
-                        items.value.forEachIndexed { index, id ->
-                            key(id) {
-                                Item(
-                                    id=id,
-                                    onMove={ amount ->
-                                        val next = index + amount
-                                        if (next >= 0 && next < items.value.size) {
-                                            items.value = items.value.move(index, index + amount)
-                                        }
+                LinearLayout(orientation=LinearLayout.VERTICAL) {
+                    items.value.forEachIndexed { index, id ->
+                        key(id) {
+                            Item(
+                                id=id,
+                                onMove={ amount ->
+                                    val next = index + amount
+                                    if (next >= 0 && next < items.value.size) {
+                                        items.value = items.value.move(index, index + amount)
                                     }
-                                )
-                            }
+                                }
+                            )
                         }
                     }
                 }
@@ -1852,14 +1842,12 @@
             @Composable
             // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
             fun Item(id: Int, onMove: (Int) -> Unit) {
-                Observe {
-                    val count = state { 0 }
-                    LinearLayout(orientation=LinearLayout.HORIZONTAL) {
-                        TextView(id=(id+$tvId), text="id: ${'$'}id amt: ${'$'}{count.value}")
-                        Button(id=(id+$btnIdAdd), text="+", onClick={ count.value++ })
-                        Button(id=(id+$btnIdUp), text="Up", onClick={ onMove(1) })
-                        Button(id=(id+$btnIdDown), text="Down", onClick={ onMove(-1) })
-                    }
+                val count = state { 0 }
+                LinearLayout(orientation=LinearLayout.HORIZONTAL) {
+                    TextView(id=(id+$tvId), text="id: ${'$'}id amt: ${'$'}{count.value}")
+                    Button(id=(id+$btnIdAdd), text="+", onClick={ count.value++ })
+                    Button(id=(id+$btnIdUp), text="Up", onClick={ onMove(1) })
+                    Button(id=(id+$btnIdDown), text="Down", onClick={ onMove(-1) })
                 }
             }
             """, noParameters,
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
index 581b9ca..2563d9d 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
@@ -27,7 +27,7 @@
     ) = verifyComposeIrTransform(
         """
             import androidx.compose.Composable
-            import androidx.compose.Direct
+            import androidx.compose.ComposableContract
 
             $checked
         """.trimIndent(),
@@ -1221,7 +1221,7 @@
                 %dirty = %dirty or if (%composer.changed(text)) 0b0100 else 0b0010
               }
               if (%changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(color)) 0b00010000 else 0b1000
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(color.value)) 0b00010000 else 0b1000
               }
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -2146,4 +2146,48 @@
             }
         """
     )
+
+    @Test
+    fun testGrouplessProperty(): Unit = comparisonPropagation(
+        """
+        """,
+        """
+            import androidx.compose.currentComposer
+
+            open class Foo {
+                @ComposableContract(readonly = true)
+                @Composable
+                inline val current: Int get() = currentComposer.hashCode()
+
+                @ComposableContract(readonly = true)
+                @Composable
+                fun getHashCode(): Int = currentComposer.hashCode()
+            }
+
+            @ComposableContract(readonly = true)
+            @Composable
+            fun getHashCode(): Int = currentComposer.hashCode()
+        """,
+        """
+            open class Foo {
+              val current: Int
+                get() {
+                  val tmp0 = %composer.hashCode()
+                  return tmp0
+                }
+              @ComposableContract(readonly = true)
+              @Composable
+              fun getHashCode(%composer: Composer<*>?, %key: Int, %changed: Int): Int {
+                val tmp0 = %composer.hashCode()
+                return tmp0
+              }
+            }
+            @ComposableContract(readonly = true)
+            @Composable
+            fun getHashCode(%composer: Composer<*>?, %key: Int, %changed: Int): Int {
+              val tmp0 = %composer.hashCode()
+              return tmp0
+            }
+        """
+    )
 }
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
index eca787c..cf79cb31 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
@@ -25,6 +25,7 @@
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.annotations.argumentValue
 import org.jetbrains.kotlin.resolve.constants.ConstantValue
 import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
 import org.jetbrains.kotlin.types.KotlinType
@@ -35,7 +36,7 @@
 object ComposeFqNames {
     val Composable = ComposeUtils.composeFqName("Composable")
     val CurrentComposerIntrinsic = ComposeUtils.composeFqName("<get-currentComposer>")
-    val Direct = ComposeUtils.composeFqName("Direct")
+    val ComposableContract = ComposeUtils.composeFqName("ComposableContract")
     val restartableFunction = FqName.fromSegments(listOf(
         "androidx",
         "compose",
@@ -78,8 +79,14 @@
                     (constructor.declarationDescriptor?.annotations?.hasStableMarker() ?: false))
 fun Annotated.hasComposableAnnotation(): Boolean =
     annotations.findAnnotation(ComposeFqNames.Composable) != null
-fun Annotated.hasDirectAnnotation(): Boolean =
-    annotations.findAnnotation(ComposeFqNames.Direct) != null
+fun Annotated.composableRestartableContract(): Boolean? {
+    val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
+    return contract.argumentValue("restartable")?.value as? Boolean
+}
+fun Annotated.composableReadonlyContract(): Boolean? {
+    val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
+    return contract.argumentValue("readonly")?.value as? Boolean
+}
 fun Annotated.hasUntrackedAnnotation(): Boolean =
     annotations.findAnnotation(ComposeFqNames.Untracked) != null
 
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
index 6356acd..3ae380f 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
@@ -115,7 +115,9 @@
 import org.jetbrains.kotlin.ir.util.TypeTranslator
 import org.jetbrains.kotlin.ir.util.endOffset
 import org.jetbrains.kotlin.ir.util.getPrimitiveArrayElementType
+import org.jetbrains.kotlin.ir.util.getPropertyGetter
 import org.jetbrains.kotlin.ir.util.getSimpleFunction
+import org.jetbrains.kotlin.ir.util.primaryConstructor
 import org.jetbrains.kotlin.ir.util.referenceFunction
 import org.jetbrains.kotlin.ir.util.startOffset
 import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -249,6 +251,25 @@
         return underlyingType.makeNullable()
     }
 
+    protected fun IrExpression.unboxValueIfInline(): IrExpression {
+        if (type.isNullable()) return this
+        val classSymbol = type.classOrNull ?: return this
+        val klass = classSymbol.bindIfNecessary().owner
+        if (klass.isInline) {
+            val primaryValueParameter = klass
+                .primaryConstructor
+                ?.valueParameters
+                ?.get(0) ?: error("Expected a value parameter")
+            val fieldGetter = klass.getPropertyGetter(primaryValueParameter.name.identifier)
+                ?: error("Expected a getter")
+            return irCall(
+                symbol = fieldGetter,
+                dispatchReceiver = this
+            ).unboxValueIfInline()
+        }
+        return this
+    }
+
     fun IrAnnotationContainer.hasComposableAnnotation(): Boolean {
         return annotations.hasAnnotation(ComposeFqNames.Composable)
     }
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
index 60cf508..dd7da32 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
@@ -19,7 +19,8 @@
 import androidx.compose.plugins.kotlin.ComposeFqNames
 import androidx.compose.plugins.kotlin.KtxNameConventions
 import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.hasDirectAnnotation
+import androidx.compose.plugins.kotlin.composableReadonlyContract
+import androidx.compose.plugins.kotlin.composableRestartableContract
 import androidx.compose.plugins.kotlin.hasUntrackedAnnotation
 import androidx.compose.plugins.kotlin.irTrace
 import androidx.compose.plugins.kotlin.isEmitInline
@@ -28,6 +29,7 @@
 import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
 import org.jetbrains.kotlin.backend.common.pop
 import org.jetbrains.kotlin.backend.common.push
+import org.jetbrains.kotlin.builtins.PrimitiveType
 import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
 import org.jetbrains.kotlin.descriptors.FunctionDescriptor
 import org.jetbrains.kotlin.descriptors.Modality
@@ -130,6 +132,16 @@
 import org.jetbrains.kotlin.resolve.BindingTrace
 import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
 import org.jetbrains.kotlin.resolve.inline.InlineUtil
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.typeUtil.isBoolean
+import org.jetbrains.kotlin.types.typeUtil.isByte
+import org.jetbrains.kotlin.types.typeUtil.isChar
+import org.jetbrains.kotlin.types.typeUtil.isDouble
+import org.jetbrains.kotlin.types.typeUtil.isFloat
+import org.jetbrains.kotlin.types.typeUtil.isInt
+import org.jetbrains.kotlin.types.typeUtil.isLong
+import org.jetbrains.kotlin.types.typeUtil.isNullableAny
+import org.jetbrains.kotlin.types.typeUtil.isShort
 import org.jetbrains.kotlin.types.typeUtil.isUnit
 import org.jetbrains.kotlin.types.typeUtil.makeNullable
 import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
@@ -430,11 +442,32 @@
     private val changedDescriptor = composerTypeDescriptor
         .unsubstitutedMemberScope
         .findFirstFunction("changed") {
-            // this is the changed(value: T) variant.
-            // TODO(lmr): Add handling for different primitive types
-            it.typeParameters.size == 1
+            it.valueParameters.first().type.isNullableAny()
         }
 
+    fun KotlinType.toPrimitiveType(): PrimitiveType? = when {
+        isInt() -> PrimitiveType.INT
+        isBoolean() -> PrimitiveType.BOOLEAN
+        isFloat() -> PrimitiveType.FLOAT
+        isLong() -> PrimitiveType.LONG
+        isDouble() -> PrimitiveType.DOUBLE
+        isByte() -> PrimitiveType.BYTE
+        isChar() -> PrimitiveType.CHAR
+        isShort() -> PrimitiveType.SHORT
+        else -> null
+    }
+
+    private val changedDescriptors = composerTypeDescriptor
+        .unsubstitutedMemberScope
+        .getContributedFunctions(Name.identifier("changed"), NoLookupLocation.FROM_BACKEND)
+        .filter { it.name.identifier == "changed" }
+        .mapNotNull { desc ->
+            desc.valueParameters.first().type.toPrimitiveType()?.let { primitive ->
+                primitive to desc
+            }
+        }
+        .toMap()
+
     private val skipToGroupEndDescriptor = composerTypeDescriptor
         .unsubstitutedMemberScope
         .findFirstFunction("skipToGroupEnd") { it.valueParameters.size == 0 }
@@ -603,7 +636,7 @@
     // 1. They are inline
     // 2. They have a return value (may get relaxed in the future)
     // 3. They are a lambda (we use RestartableFunction<...> class for this instead)
-    // 4. They are annotated as @Direct
+    // 4. They are annotated as @ComposableContract(restartable = false)
     private fun IrFunction.shouldBeRestartable(): Boolean {
         // Only insert observe scopes in non-empty composable function
         if (body == null)
@@ -615,7 +648,7 @@
         if (descriptor.isInline)
             return false
 
-        if (descriptor.hasDirectAnnotation())
+        if (descriptor.composableRestartableContract() == false)
             return false
 
         // Do not insert an observe scope in an inline composable lambda
@@ -656,6 +689,17 @@
         return false
     }
 
+    private fun IrFunction.shouldElideGroups(): Boolean {
+        var readOnly = descriptor.composableReadonlyContract()
+        if (readOnly == null && this is IrSimpleFunction) {
+            readOnly = correspondingPropertySymbol
+                ?.owner
+                ?.descriptor
+                ?.composableReadonlyContract()
+        }
+        return readOnly == true
+    }
+
     private fun IrFunction.isLambda(): Boolean {
         // There is probably a better way to determine this, but if there is, it isn't obvious
         return descriptor.name.asString() == "<anonymous>"
@@ -674,6 +718,8 @@
     ): IrStatement {
         val body = declaration.body!!
 
+        val elideGroups = declaration.shouldElideGroups()
+
         val skipPreamble = mutableStatementContainer()
         val bodyPreamble = mutableStatementContainer()
 
@@ -704,17 +750,20 @@
 
         transformed = transformed.transformChildren()
 
-        scope.realizeGroup(::irEndReplaceableGroup)
+        if (!elideGroups) scope.realizeGroup(::irEndReplaceableGroup)
 
         declaration.body = IrBlockBodyImpl(
             body.startOffset,
             body.endOffset,
             listOfNotNull(
-                irStartReplaceableGroup(body, irGet(scope.keyParameter!!)),
+                if (!elideGroups)
+                    irStartReplaceableGroup(body, irGet(scope.keyParameter!!))
+                else
+                    null,
                 *skipPreamble.statements.toTypedArray(),
                 *bodyPreamble.statements.toTypedArray(),
                 *transformed.statements.toTypedArray(),
-                irEndReplaceableGroup(),
+                if (!elideGroups) irEndReplaceableGroup() else null,
                 returnVar?.let { irReturn(declaration.symbol, irGet(it)) }
             )
         )
@@ -1731,9 +1780,23 @@
     }
 
     private fun irChanged(value: IrExpression): IrExpression {
-        return irMethodCall(irCurrentComposer(), changedDescriptor).also {
-            it.putValueArgument(0, value)
-            it.putTypeArgument(0, value.type)
+        // compose has a unique opportunity to avoid inline class boxing for changed calls, since
+        // we know that the only thing that we are detecting here is "changed or not", we can
+        // just as easily pass in the underlying value, which will avoid boxing to check for
+        // equality on recompositions. As a result here we want to pass in the underlying
+        // property value for inline classes, not the instance itself. The inline class lowering
+        // will turn this into just passing the wrapped value later on. If the type is already
+        // boxed, then we don't want to unnecessarily _unbox_ it. Note that if Kotlin allows for
+        // an overridden equals method of inline classes in the future, we may have to avoid the
+        // boxing in a different way.
+        val type = value.type.unboxInlineClass()
+        val expr = value.unboxValueIfInline()
+        val descriptor = type
+            .toKotlinType()
+            .toPrimitiveType()
+            .let { changedDescriptors[it] } ?: changedDescriptor
+        return irMethodCall(irCurrentComposer(), descriptor).also {
+            it.putValueArgument(0, expr)
         }
     }
 
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
index 3eef569..81d9aa1 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
@@ -442,7 +442,10 @@
         }
     }
 
-    private fun IrFunctionAccessExpression.printArgumentList() {
+    private fun IrFunctionAccessExpression.printArgumentList(
+        forceParameterNames: Boolean = false,
+        forceSingleLine: Boolean = false
+    ) {
         val descriptor = symbol.descriptor
         val arguments = mutableListOf<IrExpression>()
         val paramNames = mutableListOf<String>()
@@ -450,7 +453,7 @@
         val isEmit = descriptor is ComposableEmitDescriptor
         val isCompoundEmit = descriptor is ComposableEmitDescriptor && descriptor.hasChildren
         val isLeafEmit = isEmit && !isCompoundEmit
-        var useParameterNames = isEmit
+        var useParameterNames = forceParameterNames || isEmit
         for (i in 0 until valueArgumentsCount) {
             val arg = getValueArgument(i)
             if (arg != null) {
@@ -471,34 +474,41 @@
                 useParameterNames = true
             }
         }
+        val multiline = useParameterNames && !forceSingleLine
         if (arguments.isNotEmpty() || trailingLambda == null) {
             print("(")
-            if (useParameterNames) {
+            if (multiline) {
                 // if we are using parameter names, we go on multiple lines
                 println()
                 indented {
                     arguments.zip(paramNames).forEachIndexed { i, (arg, name) ->
-                        print(name)
-                        print(" = ")
+                        if (useParameterNames) {
+                            print(name)
+                            print(" = ")
+                        }
                         arg.print()
                         if (i < arguments.size - 1) println(", ")
                     }
                 }
                 println()
             } else {
-                arguments.forEachIndexed { index, it ->
-                    when (paramNames[index]) {
+                arguments.zip(paramNames).forEachIndexed { i, (arg, name) ->
+                    if (useParameterNames) {
+                        print(name)
+                        print(" = ")
+                    }
+                    when (name) {
                         KtxNameConventions.DEFAULT_PARAMETER.identifier,
                         KtxNameConventions.CHANGED_PARAMETER.identifier -> {
                             withIntsAsBinaryLiterals {
-                                it.print()
+                                arg.print()
                             }
                         }
                         else -> {
-                            it.print()
+                            arg.print()
                         }
                     }
-                    if (index < arguments.size - 1) print(", ")
+                    if (i < arguments.size - 1) print(", ")
                 }
             }
             print(")")
@@ -566,8 +576,23 @@
             print(".")
         }
         print(name)
-        if (expression.valueArgumentsCount > 0 || !isAnnotation) {
-            expression.printArgumentList()
+
+        val printArgumentList = if (!isAnnotation) true else {
+            var hasArguments = false
+            for (i in 0 until expression.valueArgumentsCount) {
+                val arg = expression.getValueArgument(i)
+                if (arg != null) {
+                    hasArguments = true
+                    break
+                }
+            }
+            hasArguments
+        }
+        if (printArgumentList) {
+            expression.printArgumentList(
+                forceParameterNames = isAnnotation,
+                forceSingleLine = isAnnotation
+            )
         }
     }
 
diff --git a/compose/compose-runtime/api/0.1.0-dev14.txt b/compose/compose-runtime/api/0.1.0-dev14.txt
index c844bd9..84779c2 100644
--- a/compose/compose-runtime/api/0.1.0-dev14.txt
+++ b/compose/compose-runtime/api/0.1.0-dev14.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
@@ -188,11 +200,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -215,8 +229,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -283,7 +297,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -309,7 +323,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/api/api_lint.ignore b/compose/compose-runtime/api/api_lint.ignore
index e2b2bd4..37cdb9f 100644
--- a/compose/compose-runtime/api/api_lint.ignore
+++ b/compose/compose-runtime/api/api_lint.ignore
@@ -69,3 +69,9 @@
     Missing nullability on method `getGroupDataKey` return
 MissingNullability: androidx.compose.SlotReader#getGroupNode():
     Missing nullability on method `getGroupNode` return
+
+
+NoByteOrShort: androidx.compose.Composer#changed(byte) parameter #0:
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter value in androidx.compose.Composer.changed(byte value)
+NoByteOrShort: androidx.compose.Composer#changed(short) parameter #0:
+    Should avoid odd sized primitives; use `int` instead of `short` in parameter value in androidx.compose.Composer.changed(short value)
diff --git a/compose/compose-runtime/api/current.txt b/compose/compose-runtime/api/current.txt
index c844bd9..84779c2 100644
--- a/compose/compose-runtime/api/current.txt
+++ b/compose/compose-runtime/api/current.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
@@ -188,11 +200,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -215,8 +229,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -283,7 +297,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -309,7 +323,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev14.txt b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev14.txt
index c844bd9..84779c2 100644
--- a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev14.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
@@ -188,11 +200,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -215,8 +229,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -283,7 +297,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -309,7 +323,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/api/public_plus_experimental_current.txt b/compose/compose-runtime/api/public_plus_experimental_current.txt
index c844bd9..84779c2 100644
--- a/compose/compose-runtime/api/public_plus_experimental_current.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_current.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
@@ -188,11 +200,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -215,8 +229,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -283,7 +297,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -309,7 +323,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/api/restricted_0.1.0-dev14.txt b/compose/compose-runtime/api/restricted_0.1.0-dev14.txt
index 712bde7..b635eb2 100644
--- a/compose/compose-runtime/api/restricted_0.1.0-dev14.txt
+++ b/compose/compose-runtime/api/restricted_0.1.0-dev14.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method @kotlin.PublishedApi internal final <T> T! consume(androidx.compose.Ambient<T> key);
@@ -201,11 +213,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -228,8 +242,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -296,7 +310,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -337,7 +351,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/api/restricted_current.txt b/compose/compose-runtime/api/restricted_current.txt
index 712bde7..b635eb2 100644
--- a/compose/compose-runtime/api/restricted_current.txt
+++ b/compose/compose-runtime/api/restricted_current.txt
@@ -79,20 +79,32 @@
   @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
   }
 
+  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
+    method public abstract boolean readonly() default false;
+    method public abstract boolean restartable() default true;
+  }
+
   public final class ComposeKt {
     method @androidx.compose.Stable public static kotlin.jvm.functions.Function0<kotlin.Unit> emptyContent();
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> implements androidx.compose.ComposerValidator {
+  public class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
     method public final void abortRoot();
     method public final <V, T> void apply(V? value, kotlin.jvm.functions.Function2<? super T,? super V,kotlin.Unit> block);
     method public final void applyChanges();
     method public final androidx.compose.CompositionReference buildReference();
     method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method public <T> boolean changed(T? value);
-    method public boolean changed(int value);
+    method public final boolean changed(Object? value);
+    method public final boolean changed(char value);
+    method public final boolean changed(byte value);
+    method public final boolean changed(short value);
+    method public final boolean changed(boolean value);
+    method public final boolean changed(float value);
+    method public final boolean changed(long value);
+    method public final boolean changed(double value);
+    method public final boolean changed(int value);
     method public final void collectKeySourceInformation();
     method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method @kotlin.PublishedApi internal final <T> T! consume(androidx.compose.Ambient<T> key);
@@ -201,11 +213,13 @@
   public interface CompositionReference {
     method public <T> T! getAmbient(androidx.compose.Ambient<T> key);
     method public androidx.compose.BuildableMap<androidx.compose.Ambient<java.lang.Object>,androidx.compose.State<java.lang.Object>> getAmbientScope();
+    method public int getCompoundHashKey();
     method public void invalidate();
     method public <N> void registerComposer(androidx.compose.Composer<N> composer);
+    property public abstract int compoundHashKey;
   }
 
-  @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
+  @Deprecated @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Direct {
   }
 
   public final class EffectsKt {
@@ -228,8 +242,8 @@
 
   public final class FlowAdapterKt {
     method @androidx.compose.Composable @kotlinx.coroutines.ExperimentalCoroutinesApi public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.StateFlow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
-    method @androidx.compose.Composable public static <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, T? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @Deprecated @androidx.compose.Composable public static inline <T> androidx.compose.State<T> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
+    method @androidx.compose.Composable public static <T extends R, R> androidx.compose.State<R> collectAsState(kotlinx.coroutines.flow.Flow<? extends T>, R? initial, kotlin.coroutines.CoroutineContext context = Dispatchers.Main);
   }
 
   public final class FrameManager {
@@ -296,7 +310,7 @@
   }
 
   public final class ObserveKt {
-    method @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Observe(kotlin.jvm.functions.Function0<kotlin.Unit> body);
   }
 
   public final class ObserverMap<K, V> {
@@ -337,7 +351,7 @@
   }
 
   public final class RecomposeKt {
-    method @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
+    method @Deprecated @androidx.compose.Composable public static void Recompose(kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> body);
   }
 
   public abstract class Recomposer {
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/HotReloadIntegrationTests.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/HotReloadIntegrationTests.kt
index 7b9bb1f..a8cc6a6 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/HotReloadIntegrationTests.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/HotReloadIntegrationTests.kt
@@ -20,7 +20,6 @@
 import androidx.compose.benchmark.ComposeActivity
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.WithConstraints
 import androidx.ui.core.setContent
 import androidx.ui.foundation.Text
@@ -46,8 +45,9 @@
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class HotReloadIntegrationTests {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(ComposeActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(ComposeActivity::class.java)
 
     @Test
     fun testSubComposition() {
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
index 0e32118..c4b2ecc 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
@@ -17,7 +17,6 @@
 package androidx.compose.benchmark
 
 import androidx.compose.Composable
-import androidx.compose.Observe
 import androidx.compose.benchmark.realworld4.RealWorld4_FancyWidget_000
 import androidx.compose.getValue
 import androidx.compose.mutableStateOf
@@ -185,6 +184,8 @@
     Box(modifier = model.modifier)
 }
 
+@Composable fun Observe(body: @Composable () -> Unit) = body()
+
 @Composable
 fun TenRects(model: ColorModel, narrow: Boolean = false) {
     if (narrow) {
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmarkBase.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmarkBase.kt
index 6c3caf0..01abcb6 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmarkBase.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmarkBase.kt
@@ -28,7 +28,6 @@
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
 import androidx.compose.currentComposer
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.AndroidOwner
 import androidx.ui.core.setContent
 import org.junit.Assert.assertTrue
@@ -38,8 +37,9 @@
     @get:Rule
     val benchmarkRule = BenchmarkRule()
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(ComposeActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(ComposeActivity::class.java)
 
     fun measureCompose(block: @Composable () -> Unit) {
         val activity = activityRule.activity
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/SiblingBenchmark.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/SiblingBenchmark.kt
index f269745..7eb1b41 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/SiblingBenchmark.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/SiblingBenchmark.kt
@@ -24,7 +24,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -98,7 +97,8 @@
 }
 
 // NOTE: remove when SAM conversion works in IR
-fun ActivityTestRule<ComposeActivity>.runUiRunnable(block: () -> Unit) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<ComposeActivity>.runUiRunnable(block: () -> Unit) {
     runOnUiThread(object : Runnable {
         override fun run() {
             block()
diff --git a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/FlowAdapterSamples.kt b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/FlowAdapterSamples.kt
index 5864012..ab0dcde 100644
--- a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/FlowAdapterSamples.kt
+++ b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/FlowAdapterSamples.kt
@@ -27,13 +27,6 @@
 
 @Sampled
 @Composable
-fun FlowSample(flow: Flow<String>) {
-    val value: String? by flow.collectAsState()
-    Text("Value is $value")
-}
-
-@Sampled
-@Composable
 fun FlowWithInitialSample(flow: Flow<String>) {
     val value: String by flow.collectAsState("initial")
     Text("Value is $value")
diff --git a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/RecomposeSamples.kt b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/RecomposeSamples.kt
deleted file mode 100644
index 8e98abe..0000000
--- a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/RecomposeSamples.kt
+++ /dev/null
@@ -1,62 +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.compose.samples
-
-import androidx.annotation.Sampled
-import androidx.compose.Composable
-import androidx.compose.Recompose
-import androidx.compose.remember
-import androidx.ui.foundation.TextField
-import androidx.ui.foundation.Text
-import androidx.ui.material.Button
-import androidx.ui.foundation.TextFieldValue
-
-@Composable
-@Sampled
-fun recomposeSample() {
-    class LoginState(var username: TextFieldValue, var password: TextFieldValue) {
-        fun login() = Api.login(username.text, password.text)
-    }
-
-    @Composable
-    fun LoginScreen() {
-        val model = remember { LoginState(
-            TextFieldValue("user"),
-            TextFieldValue("pass")
-        ) }
-
-        Recompose { recompose ->
-            TextField(
-                value = model.username,
-                onValueChange = {
-                    model.username = it
-                    recompose()
-                }
-            )
-            TextField(
-                value = model.password,
-                onValueChange = {
-                    model.password = it
-                    recompose()
-                }
-            )
-            Button(onClick = { model.login() }) {
-                Text("Login")
-            }
-        }
-    }
-}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
index 05a99b7..dfb134c 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
@@ -20,7 +20,6 @@
 import androidx.compose.Ambient
 import androidx.compose.Composable
 import androidx.compose.CompositionReference
-import androidx.compose.Observe
 import androidx.compose.Providers
 import androidx.compose.Recomposer
 import androidx.compose.StructurallyEqual
@@ -505,22 +504,6 @@
         }
     }
 
-    @Composable
-    fun subCompose(block: @Composable () -> Unit) {
-        val container =
-            remember { escapeCompose { LayoutNode() } }
-        val reference = compositionReference()
-        // TODO(b/150390669): Review use of @Untracked
-        subcomposeInto(
-            activityRule.activity,
-            container,
-            Recomposer.current(),
-            reference
-        ) @Untracked {
-            block()
-        }
-    }
-
     class Ref<T : Any> {
         lateinit var value: T
     }
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
index 75da95e..b061a67 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
@@ -30,8 +30,14 @@
 import androidx.compose.Composition
 import androidx.compose.FrameManager
 import androidx.compose.Looper
-import androidx.test.rule.ActivityTestRule
+import androidx.compose.Recomposer
+import androidx.compose.Untracked
+import androidx.compose.compositionReference
+import androidx.compose.escapeCompose
+import androidx.compose.remember
+import androidx.ui.core.LayoutNode
 import androidx.ui.core.setViewContent
+import androidx.ui.core.subcomposeInto
 
 class TestActivity : Activity() {
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -41,7 +47,8 @@
         })
     }
 }
-fun makeTestActivityRule() = ActivityTestRule(TestActivity::class.java)
+@Suppress("DEPRECATION")
+fun makeTestActivityRule() = androidx.test.rule.ActivityTestRule(TestActivity::class.java)
 
 private val ROOT_ID = 18284847
 
@@ -101,7 +108,8 @@
 
 abstract class BaseComposeTest {
 
-    abstract val activityRule: ActivityTestRule<TestActivity>
+    @Suppress("DEPRECATION")
+    abstract val activityRule: androidx.test.rule.ActivityTestRule<TestActivity>
 
     val activity get() = activityRule.activity
 
@@ -118,6 +126,22 @@
         activity,
         composable
     )
+
+    @Composable
+    fun subCompose(block: @Composable () -> Unit) {
+        val container =
+            remember { escapeCompose { LayoutNode() } }
+        val reference = compositionReference()
+        // TODO(b/150390669): Review use of @Untracked
+        subcomposeInto(
+            activityRule.activity,
+            container,
+            Recomposer.current(),
+            reference
+        ) @Untracked {
+            block()
+        }
+    }
 }
 
 sealed class ComposeTester(val activity: Activity, val composable: @Composable () -> Unit) {
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
index 6ab3e06..5c06179 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
@@ -18,7 +18,6 @@
 
 import android.widget.TextView
 import androidx.compose.Composable
-import androidx.compose.Observe
 import androidx.compose.clearRoots
 import androidx.compose.frames.AbstractRecord
 import androidx.compose.frames.Framed
@@ -89,6 +88,8 @@
     }
 }
 
+@Composable fun Observe(body: @Composable () -> Unit) = body()
+
 class TestState<T>(value: T) : Framed {
     @Suppress("UNCHECKED_CAST")
     var value: T
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/CompoundHashKeyTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/CompoundHashKeyTests.kt
new file mode 100644
index 0000000..f29c4bdb
--- /dev/null
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/CompoundHashKeyTests.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.compose.test
+
+import androidx.compose.Composable
+import androidx.compose.currentComposer
+import androidx.compose.invalidate
+import androidx.compose.key
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.runner.RunWith
+import org.junit.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class CompoundHashKeyTests : BaseComposeTest() {
+    @get:Rule
+    override val activityRule = makeTestActivityRule()
+
+    @Test // b/157905524
+    fun testWithSubCompose() {
+        val outerKeys = mutableListOf<Int>()
+        val innerKeys = mutableListOf<Int>()
+        val invalidates = mutableListOf<() -> Unit>()
+        fun invalidateComposition() {
+            invalidates.forEach { it() }
+            invalidates.clear()
+        }
+        @Composable
+        fun recordHashKeys() {
+            invalidates.add(invalidate)
+            outerKeys.add(currentComposer.currentCompoundKeyHash)
+            subCompose {
+                invalidates.add(invalidate)
+                innerKeys.add(currentComposer.currentCompoundKeyHash)
+            }
+        }
+
+        val firstOuter = mutableListOf<Int>()
+        val firstInner = mutableListOf<Int>()
+        compose {
+            (0..1).forEach {
+                key(it) {
+                    recordHashKeys()
+                }
+            }
+        }.then {
+            assertEquals(2, outerKeys.size)
+            assertEquals(2, innerKeys.size)
+            assertNotEquals(outerKeys[0], outerKeys[1])
+            assertNotEquals(innerKeys[0], innerKeys[1])
+
+            firstOuter.addAll(outerKeys)
+            outerKeys.clear()
+            firstInner.addAll(innerKeys)
+            innerKeys.clear()
+            invalidateComposition()
+        }.then {
+            assertEquals(firstInner, innerKeys)
+            assertEquals(firstOuter, outerKeys)
+        }
+    }
+}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
index aa0bf3f..e15243b 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
@@ -20,7 +20,6 @@
 import android.widget.TextView
 import androidx.compose.Composable
 import androidx.compose.Providers
-import androidx.compose.Recompose
 import androidx.compose.State
 import androidx.compose.ambientOf
 import androidx.compose.clearRoots
@@ -669,12 +668,10 @@
         }
 
         @Composable fun SimpleComposable() {
-            Recompose {
-                requestRecompose = it
-                Providers(MyAmbient provides ambientValue++) {
-                    SimpleComposable2()
-                    Button(id = 123)
-                }
+            requestRecompose = invalidate
+            Providers(MyAmbient provides ambientValue++) {
+                SimpleComposable2()
+                Button(id = 123)
             }
         }
 
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/FlowAdapterTest.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/FlowAdapterTest.kt
index ae8b766..9e28a46 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/FlowAdapterTest.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/FlowAdapterTest.kt
@@ -57,6 +57,7 @@
         val stream = FlowChannel<String>()
         var realValue: String? = "to-be-updated"
         rule.setContent {
+            @Suppress("DEPRECATION")
             realValue = stream.flow.collectAsState().value
         }
 
@@ -71,7 +72,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState().value
+            realValue = stream.flow.collectAsState(initial = null).value
         }
 
         runOnIdleCompose {
@@ -89,7 +90,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState().value
+            realValue = stream.flow.collectAsState(initial = null).value
         }
 
         runOnIdleCompose {
@@ -113,7 +114,7 @@
         var realValue: String? = "to-be-updated"
         rule.setContent {
             if (emit) {
-                realValue = stream.flow.collectAsState().value
+                realValue = stream.flow.collectAsState(initial = null).value
             }
         }
 
@@ -183,7 +184,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState().value
+            realValue = stream.flow.collectAsState(initial = null).value
         }
 
         runOnIdleCompose {
@@ -211,7 +212,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState().value
+            realValue = stream.flow.collectAsState(initial = null).value
         }
 
         runOnIdleCompose {
@@ -234,7 +235,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState(Dispatchers.Default).value
+            realValue = stream.flow.collectAsState(null, Dispatchers.Default).value
             if (realValue != null) {
                 latch.countDown()
             }
@@ -258,7 +259,7 @@
 
         var realValue: String? = null
         rule.setContent {
-            realValue = stream.flow.collectAsState(context).value
+            realValue = stream.flow.collectAsState(null, context).value
         }
 
         runOnIdleCompose {
@@ -288,6 +289,19 @@
     }
 
     @Test
+    fun stateFlowHandlesNullValue() {
+        val flow = MutableStateFlow<String?>(null)
+        var realValue: String? = "to-be-updated"
+        rule.setContent {
+            realValue = flow.collectAsState().value
+        }
+
+        runOnIdleCompose {
+            assertThat(realValue).isNull()
+        }
+    }
+
+    @Test
     fun updatingValueOfStateFlow() {
         val flow = MutableStateFlow("initial")
         var realValue = "to-be-updated"
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
index 68fa64c..5e3d7c8 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
@@ -21,11 +21,7 @@
 import android.widget.LinearLayout
 import android.widget.TextView
 import androidx.compose.Composable
-import androidx.compose.Recomposer
-import androidx.compose.Untracked
 import androidx.compose.clearRoots
-import androidx.compose.compositionReference
-import androidx.compose.escapeCompose
 import androidx.compose.frames.currentFrame
 import androidx.compose.getValue
 import androidx.compose.invalidate
@@ -35,8 +31,6 @@
 import androidx.compose.setValue
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.core.LayoutNode
-import androidx.ui.core.subcomposeInto
 import androidx.ui.node.UiComposer
 import junit.framework.TestCase.assertEquals
 import junit.framework.TestCase.assertFalse
@@ -439,22 +433,6 @@
             assertNotSame(frameId, currentFrame().id)
         }
     }
-
-    @Composable
-    fun subCompose(block: @Composable () -> Unit) {
-        val container =
-            remember { escapeCompose { LayoutNode() } }
-        val reference = compositionReference()
-        // TODO(b/150390669): Review use of @Untracked
-        subcomposeInto(
-            activityRule.activity,
-            container,
-            Recomposer.current(),
-            reference
-        ) @Untracked {
-            block()
-        }
-    }
 }
 
 @Composable
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
index c77953e..cdf26f7 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
@@ -19,7 +19,7 @@
 import android.os.Debug
 import android.widget.TextView
 import androidx.compose.Composable
-import androidx.compose.Direct
+import androidx.compose.ComposableContract
 import androidx.compose.clearRoots
 import androidx.compose.mutableStateOf
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -263,7 +263,7 @@
 }
 
 @Composable
-@Direct
+@ComposableContract(restartable = false)
 fun DirectNothing() {
 }
 
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
index f2f087f..c71b9c7 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
@@ -68,6 +68,7 @@
      *
      * @sample androidx.compose.samples.consumeAmbient
      */
+    @ComposableContract(readonly = true)
     @Composable
     inline val current: T get() = currentComposer.consume(this)
 }
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
new file mode 100644
index 0000000..91aec87
--- /dev/null
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
@@ -0,0 +1,45 @@
+/*
+ * 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.compose
+
+/**
+ * This annotation can be applied to [Composable] functions and provide metadata to the compiler
+ * that imply compose-specific contracts that the author of the function is guaranteeing the
+ * function complies with. This metadata can be used to generate more efficient code.
+ *
+ * Caution: Use of this annotation means that the annotated declaration *MUST* comply with those
+ * contracts, or else the resulting code's behavior will be undefined.
+ *
+ * @param restartable When false,this will prevent code from being generated which
+ * allow this function's execution to be skipped or restarted. This may be desirable for small
+ * functions which just directly call another composable function and have very little machinery
+ * in them directly.
+ *
+ * @param readonly if false, no group will be generated around the body of the function it annotates
+ * . This is not safe unless the body of the function only executes "read" operations on the
+ * passed in composer..
+ */
+@MustBeDocumented
+@Retention(AnnotationRetention.BINARY)
+@Target(
+    AnnotationTarget.FUNCTION,
+    AnnotationTarget.PROPERTY
+)
+annotation class ComposableContract(
+    val restartable: Boolean = true,
+    val readonly: Boolean = false
+)
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
index 444d853..a8c2e54 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
@@ -340,7 +340,7 @@
      * Manager for scheduling recompositions.
      */
     val recomposer: Recomposer
-) : ComposerValidator {
+) {
     private val changes = mutableListOf<Change<N>>()
     private val lifecycleObservers = HashMap<
         CompositionLifecycleObserverHolder,
@@ -538,6 +538,7 @@
             parentProvider = parentRef.getAmbientScope()
             providersInvalidStack.push(providersInvalid.asInt())
             providersInvalid = changed(parentProvider)
+            startGroup(parentRef.compoundHashKey)
         }
     }
 
@@ -546,6 +547,9 @@
      * the composition.
      */
     fun endRoot() {
+        if (parentReference != null) {
+            endGroup()
+        }
         endGroup()
         recordEndRoot()
         finalizeCompose()
@@ -818,8 +822,8 @@
      *
      * @param value the value to be compared.
      */
-    override fun <T> changed(value: T): Boolean {
-        return if (nextSlot() != value || inserting) {
+    fun changed(value: Any?): Boolean {
+        return if (nextSlot() != value) {
             updateValue(value)
             true
         } else {
@@ -827,14 +831,84 @@
         }
     }
 
-    // TODO: Add more overloads for common primitive types like String and Float etc to avoid boxing
-    override fun changed(value: Int): Boolean {
-        return if (nextSlot() != value || inserting) {
-            updateValue(value)
-            true
-        } else {
-            false
+    fun changed(value: Char): Boolean {
+        val next = nextSlot()
+        if (next is Char) {
+            val nextPrimitive: Char = next
+            if (value == nextPrimitive) return false
         }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Byte): Boolean {
+        val next = nextSlot()
+        if (next is Byte) {
+            val nextPrimitive: Byte = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Short): Boolean {
+        val next = nextSlot()
+        if (next is Short) {
+            val nextPrimitive: Short = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Boolean): Boolean {
+        val next = nextSlot()
+        if (next is Boolean) {
+            val nextPrimitive: Boolean = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Float): Boolean {
+        val next = nextSlot()
+        if (next is Float) {
+            val nextPrimitive: Float = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Long): Boolean {
+        val next = nextSlot()
+        if (next is Long) {
+            val nextPrimitive: Long = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Double): Boolean {
+        val next = nextSlot()
+        if (next is Double) {
+            val nextPrimitive: Double = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
+    }
+
+    fun changed(value: Int): Boolean {
+        val next = nextSlot()
+        if (next is Int) {
+            val nextPrimitive: Int = next
+            if (value == nextPrimitive) return false
+        }
+        updateValue(value)
+        return true
     }
 
     /**
@@ -1004,7 +1078,7 @@
         if (ref == null || !inserting) {
             val scope = invalidateStack.peek()
             scope.used = true
-            ref = CompositionReferenceImpl(scope)
+            ref = CompositionReferenceImpl(scope, currentCompoundKeyHash)
             updateValue(ref)
         }
         endGroup()
@@ -2026,7 +2100,10 @@
         }
     }
 
-    private inner class CompositionReferenceImpl(val scope: RecomposeScope) : CompositionReference,
+    private inner class CompositionReferenceImpl(
+        val scope: RecomposeScope,
+        override val compoundHashKey: Int
+    ) : CompositionReference,
         CompositionLifecycleObserver {
 
         val composers = mutableSetOf<Composer<*>>()
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionReference.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionReference.kt
index 4ed6f8e..40f9eb7 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionReference.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionReference.kt
@@ -26,6 +26,7 @@
  * @see compositionReference
  */
 interface CompositionReference {
+    val compoundHashKey: Int
     fun <T> getAmbient(key: Ambient<T>): T
     fun invalidate()
     fun <N> registerComposer(composer: Composer<N>)
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Direct.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Direct.kt
index 1e62fc2..c047f6b 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Direct.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Direct.kt
@@ -27,4 +27,12 @@
 @Target(
     AnnotationTarget.FUNCTION
 )
+@Deprecated(
+    "Use ComposableContract instead",
+    replaceWith = ReplaceWith(
+        "ComposableContract(restartable = false)",
+        "androidx.compose.ComposableContract"
+    ),
+    level = DeprecationLevel.ERROR
+)
 annotation class Direct
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Observe.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Observe.kt
index 78284b2..33131a7 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Observe.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Observe.kt
@@ -29,5 +29,12 @@
  * @see invalidate
  * @see Recompose
  */
+@Suppress("DeprecatedCallableAddReplaceWith")
 @Composable
+@Deprecated(
+    "Observe is no longer a useful abstraction. If you need to replicate it, its implementation " +
+            "can be replicated by just creating a composable function which executes a composable" +
+            " lambda parameter. For example, " +
+            "`@Composable fun Observe(body: @Composable () -> Unit) = body()"
+)
 fun Observe(body: @Composable () -> Unit) = body()
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recompose.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recompose.kt
index 185f5d6..cd32a49 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recompose.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recompose.kt
@@ -25,15 +25,16 @@
  * maintain local state inside of composables. For cases where this is impractical, Recompose can
  * help you.
  *
- * Example:
- *
- * @sample androidx.compose.samples.recomposeSample
- *
- * Note: The above example can be done without [Recompose] by using [state].
- *
  * @see state
  * @see Observe
  * @see invalidate
  */
 @Composable
+@Deprecated(
+    "The Recompose composable is no longer a useful abstraction. Most recomposition should happen" +
+            " as a result of MutableState assignments. For anything beyond that, it is " +
+            "recommended that you use the `invalidate` function to trigger a recomposition of the" +
+            " current scope.",
+    replaceWith = ReplaceWith("val recompose = invalidate")
+)
 fun Recompose(body: @Composable (recompose: () -> Unit) -> Unit) = body(invalidate)
diff --git a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/FlowAdapter.kt b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/FlowAdapter.kt
index 693d7bc..8b46b06 100644
--- a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/FlowAdapter.kt
+++ b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/FlowAdapter.kt
@@ -38,7 +38,7 @@
 @ExperimentalCoroutinesApi
 @Suppress("NOTHING_TO_INLINE")
 @Composable
-inline fun <T : Any> StateFlow<T>.collectAsState(
+inline fun <T> StateFlow<T>.collectAsState(
     context: CoroutineContext = Dispatchers.Main
 ): State<T> = collectAsState(value, context)
 
@@ -47,13 +47,16 @@
  * would be new value posted into the [Flow] the returned [State] will be updated causing
  * recomposition of every [State.value] usage.
  *
- * @sample androidx.compose.samples.FlowSample
- *
  * @param context [CoroutineContext] to use for collecting.
  */
+@Deprecated(
+    "Either use collectAsState with an explicit initial value, " +
+            "or convert your Flow to a StateFlow.",
+    ReplaceWith("collectAsState(null, context)")
+)
 @Suppress("NOTHING_TO_INLINE")
 @Composable
-inline fun <T : Any> Flow<T>.collectAsState(
+inline fun <T> Flow<T>.collectAsState(
     context: CoroutineContext = Dispatchers.Main
 ): State<T?> = collectAsState(null, context)
 
@@ -67,10 +70,10 @@
  * @param context [CoroutineContext] to use for collecting.
  */
 @Composable
-fun <T> Flow<T>.collectAsState(
-    initial: T,
+fun <T : R, R> Flow<T>.collectAsState(
+    initial: R,
     context: CoroutineContext = Dispatchers.Main
-): State<T> {
+): State<R> {
     val state = state { initial }
     onPreCommit(this, context) {
         val job = CoroutineScope(context).launch {
diff --git a/compose/compose-runtime/src/unitTest/kotlin/androidx/compose/CompositionTests.kt b/compose/compose-runtime/src/unitTest/kotlin/androidx/compose/CompositionTests.kt
index 4e9c083..7688553 100644
--- a/compose/compose-runtime/src/unitTest/kotlin/androidx/compose/CompositionTests.kt
+++ b/compose/compose-runtime/src/unitTest/kotlin/androidx/compose/CompositionTests.kt
@@ -42,6 +42,8 @@
 import kotlin.test.assertNotEquals
 import kotlin.test.assertTrue
 
+@Composable fun Container(body: @Composable () -> Unit) = body()
+
 @Stable
 class CompositionTests {
 
@@ -1299,7 +1301,7 @@
                     text("Some text")
                 }
 
-                Observe {
+                Container {
                     text("Some text")
 
                     // Force the invalidation to survive the compose
@@ -1840,7 +1842,7 @@
         fun MockComposeScope.test() {
             outerInvalidate = invalidate
             outerKeys.add(composer.currentCompoundKeyHash)
-            Observe {
+            Container {
                 innerInvalidate = invalidate
                 innerKeys.add(composer.currentCompoundKeyHash)
             }
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
index d30a4e5..e2ec8f0 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Rule
@@ -39,7 +38,10 @@
 @SdkSuppress(minSdkVersion = 19)
 @MediumTest
 class TransitionTest {
-    @JvmField @Rule val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @JvmField @Rule val rule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
 
     private lateinit var transition: Transition
 
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewWithActivityTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewWithActivityTest.kt
index 3819e42..da7774e 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewWithActivityTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewWithActivityTest.kt
@@ -21,7 +21,6 @@
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import androidx.core.TestActivity
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Rule
@@ -29,8 +28,9 @@
 
 @MediumTest
 class ViewWithActivityTest {
+    @Suppress("DEPRECATION")
     @JvmField @Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var view: View
 
     @Before
diff --git a/core/core/src/androidTest/assets/fonts/thin_italic.ttf b/core/core/src/androidTest/assets/fonts/thin_italic.ttf
new file mode 100644
index 0000000..e8f2bee
--- /dev/null
+++ b/core/core/src/androidTest/assets/fonts/thin_italic.ttf
Binary files differ
diff --git a/core/core/src/androidTest/assets/fonts/thin_italic.ttx b/core/core/src/androidTest/assets/fonts/thin_italic.ttx
new file mode 100644
index 0000000..3349bb3
--- /dev/null
+++ b/core/core/src/androidTest/assets/fonts/thin_italic.ttx
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="100"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Thin Italic
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-ThinItalic
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/core/src/androidTest/java/androidx/core/app/NavUtilsTest.kt b/core/core/src/androidTest/java/androidx/core/app/NavUtilsTest.kt
index fbf7db3..76d4dce 100644
--- a/core/core/src/androidTest/java/androidx/core/app/NavUtilsTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/app/NavUtilsTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -33,8 +32,13 @@
 @RunWith(AndroidJUnit4::class)
 class NavUtilsTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(NavUtilsActivity::class.java, false, false)
+    val activityRule = androidx.test.rule.ActivityTestRule(
+        NavUtilsActivity::class.java,
+        false,
+        false
+    )
 
     @Test
     fun testGetParentActivityName() {
diff --git a/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
index d949a3b..1cf27cd 100644
--- a/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
@@ -312,6 +312,17 @@
         assertNotSame(Typeface.DEFAULT, font);
     }
 
+    @Test
+    public void testGetFont_adjustDisplayStyle() {
+        Typeface tf = ResourcesCompat.getFont(mContext, R.font.thin_italic);
+
+        assertNotNull(tf);
+        if (Build.VERSION.SDK_INT >= 28) {
+            assertEquals(100, tf.getWeight());
+        }
+        assertEquals(Typeface.ITALIC, tf.getStyle());
+    }
+
     private static final class FontCallback extends ResourcesCompat.FontCallback {
         private final CountDownLatch mLatch;
         Typeface mTypeface;
diff --git a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
index 8c43046..d48ce19 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
@@ -25,7 +25,6 @@
 import androidx.core.view.NestedScrollingParent3
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.hamcrest.MatcherAssert.assertThat
 import org.hamcrest.Matchers.closeTo
 import org.junit.Before
@@ -52,9 +51,10 @@
     private lateinit var mNestedScrollingParent: NestedScrollingParent
     private lateinit var mNestedScrollView: NestedScrollViewUnderTest
 
+    @Suppress("DEPRECATION")
     @Rule
     @JvmField
-    var mActivityRule = ActivityTestRule(TestContentViewActivity::class.java)
+    var mActivityRule = androidx.test.rule.ActivityTestRule(TestContentViewActivity::class.java)
 
     @Before
     @Throws(Throwable::class)
diff --git a/core/core/src/androidTest/res/font/thin_italic.ttf b/core/core/src/androidTest/res/font/thin_italic.ttf
new file mode 100644
index 0000000..e8f2bee
--- /dev/null
+++ b/core/core/src/androidTest/res/font/thin_italic.ttf
Binary files differ
diff --git a/core/core/src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java b/core/core/src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java
index c05d0ae..64c6436 100644
--- a/core/core/src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java
+++ b/core/core/src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java
@@ -142,18 +142,17 @@
     public Typeface createFromResourcesFontFile(
             Context context, Resources resources, int id, String path, int style) {
         FontFamily family = null;
+        Font font = null;
         try {
-            family = new FontFamily.Builder(new Font.Builder(resources, id).build()).build();
+            font = new Font.Builder(resources, id).build();
+            family = new FontFamily.Builder(font).build();
         } catch (IOException e) {
             return null;
         }
-        final FontStyle defaultStyle = new FontStyle(
-                (style & Typeface.BOLD) != 0 ? FontStyle.FONT_WEIGHT_BOLD
-                        : FontStyle.FONT_WEIGHT_NORMAL,
-                (style & Typeface.ITALIC) != 0 ? FontStyle.FONT_SLANT_ITALIC
-                        : FontStyle.FONT_SLANT_UPRIGHT
-        );
-        return new Typeface.CustomFallbackBuilder(family).setStyle(defaultStyle).build();
+        return new Typeface.CustomFallbackBuilder(family)
+                // Set font's style to the display style for backward compatibility.
+                .setStyle(font.getStyle())
+                .build();
     }
 
 }
diff --git a/core/core/src/main/java/androidx/core/graphics/drawable/IconCompat.java b/core/core/src/main/java/androidx/core/graphics/drawable/IconCompat.java
index ab29919..694bfb9 100644
--- a/core/core/src/main/java/androidx/core/graphics/drawable/IconCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/drawable/IconCompat.java
@@ -248,7 +248,7 @@
                 throw new IllegalArgumentException("Icon resource cannot be found");
             }
         } else {
-            rep.mObj1 = "";
+            rep.mObj1 = pkg;
         }
         rep.mString1 = pkg;
         return rep;
diff --git a/dynamic-animation/dynamic-animation-ktx/src/androidTest/java/androidx/dynamicanimation/tests/DynamicAnimationTest.kt b/dynamic-animation/dynamic-animation-ktx/src/androidTest/java/androidx/dynamicanimation/tests/DynamicAnimationTest.kt
index d94c4fc..36afde87 100644
--- a/dynamic-animation/dynamic-animation-ktx/src/androidTest/java/androidx/dynamicanimation/tests/DynamicAnimationTest.kt
+++ b/dynamic-animation/dynamic-animation-ktx/src/androidTest/java/androidx/dynamicanimation/tests/DynamicAnimationTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -45,7 +44,8 @@
 @RunWith(AndroidJUnit4::class)
 class DynamicAnimationTest {
 
-    @get:Rule val activityTestRule = ActivityTestRule<AnimationActivity>(
+    @Suppress("DEPRECATION")
+    @get:Rule val activityTestRule = androidx.test.rule.ActivityTestRule<AnimationActivity>(
         AnimationActivity::class.java)
 
     private lateinit var view: View
diff --git a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentManagerTest.kt b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentManagerTest.kt
index fe0de65..6c8c726 100644
--- a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentManagerTest.kt
+++ b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentManagerTest.kt
@@ -2,7 +2,6 @@
 
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -10,7 +9,9 @@
 @SmallTest
 @Suppress("DEPRECATION")
 class FragmentManagerTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @get:Rule val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
index 9e33942..ada4ace 100644
--- a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
+++ b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
@@ -19,14 +19,16 @@
 import android.os.Bundle
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 
 @SmallTest
 class FragmentTransactionTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @get:Rule val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
index b840dc5..a517c09 100644
--- a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
+++ b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
@@ -22,7 +22,6 @@
 import androidx.lifecycle.ViewModelProvider
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -30,8 +29,9 @@
 
 @MediumTest
 class FragmentViewModelLazyTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
 
     @UiThreadTest
     @Test
diff --git a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/ViewTest.kt b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/ViewTest.kt
index d1eb53a..bfb9a36 100644
--- a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/ViewTest.kt
+++ b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/ViewTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.fail
@@ -36,7 +35,10 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class ViewTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @get:Rule val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/fragment/fragment-truth/src/androidTest/java/androidx/fragment/app/truth/FragmentSubjectTest.kt b/fragment/fragment-truth/src/androidTest/java/androidx/fragment/app/truth/FragmentSubjectTest.kt
index c39c7fb..219e9f0 100644
--- a/fragment/fragment-truth/src/androidTest/java/androidx/fragment/app/truth/FragmentSubjectTest.kt
+++ b/fragment/fragment-truth/src/androidTest/java/androidx/fragment/app/truth/FragmentSubjectTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.assertThrows
 import org.junit.Before
 import org.junit.Rule
@@ -33,8 +32,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class FragmentSubjectTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(TestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(TestActivity::class.java)
 
     private lateinit var activity: TestActivity
 
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 6547017..fd9bb8e 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -41,7 +41,7 @@
     api(project(":lifecycle:lifecycle-livedata-core"))
     api(project(":lifecycle:lifecycle-viewmodel"))
     api(project(":lifecycle:lifecycle-viewmodel-savedstate"))
-    api(project(":savedstate:savedstate"))
+    api("androidx.savedstate:savedstate:1.1.0-alpha01")
 
     androidTestImplementation("androidx.appcompat:appcompat:1.1.0", {
         exclude group: 'androidx.fragment', module: 'fragment'
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ActivityLeakTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ActivityLeakTest.kt
index 81251da..ea1aa11 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ActivityLeakTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ActivityLeakTest.kt
@@ -18,7 +18,6 @@
 
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.RecreatedActivity
 import androidx.testutils.recreate
 import androidx.testutils.runOnUiThreadRethrow
@@ -83,8 +82,9 @@
         }
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(ActivityLeakActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(ActivityLeakActivity::class.java)
 
     @Test
     fun testActivityDoesNotLeak() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackStateTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackStateTest.kt
index 3b74026..2843ded 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackStateTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackStateTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.fail
 import org.junit.Rule
@@ -34,8 +33,9 @@
 @LargeTest
 class BackStackStateTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @Test
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ChildFragmentStateTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ChildFragmentStateTest.kt
index de0e5f2..0346592 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ChildFragmentStateTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ChildFragmentStateTest.kt
@@ -21,7 +21,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 
 import org.junit.Rule
@@ -31,8 +30,9 @@
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class ChildFragmentStateTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     @UiThreadTest
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ContentViewTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ContentViewTest.kt
index e0e09da..a11756c 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ContentViewTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ContentViewTest.kt
@@ -19,7 +19,6 @@
 import androidx.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -28,8 +27,13 @@
 @MediumTest
 class ContentViewTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(ContentViewActivity::class.java, false, false)
+    var activityRule = androidx.test.rule.ActivityTestRule(
+        ContentViewActivity::class.java,
+        false,
+        false
+    )
 
     @Test
     fun testContentViewWithInflatedFragment() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
index 7de3ac5..91f107d 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
@@ -24,12 +24,12 @@
 import androidx.core.app.ActivityCompat
 import androidx.lifecycle.ViewModelStore
 import androidx.lifecycle.ViewModelStoreOwner
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import java.io.FileDescriptor
 import java.io.PrintWriter
 
-fun ActivityTestRule<out FragmentActivity>.startupFragmentController(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.startupFragmentController(
     viewModelStore: ViewModelStore,
     savedState: Parcelable? = null
 ): FragmentController {
@@ -52,7 +52,8 @@
 }
 
 fun FragmentController.restart(
-    rule: ActivityTestRule<out FragmentActivity>,
+    @Suppress("DEPRECATION")
+    rule: androidx.test.rule.ActivityTestRule<out FragmentActivity>,
     viewModelStore: ViewModelStore,
     destroyNonConfig: Boolean = true
 ): FragmentController {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
index b9f4a18..ae48e7c 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
@@ -25,7 +25,6 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleEventObserver
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -91,8 +90,11 @@
         }
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityTestRule = androidx.test.rule.ActivityTestRule(
+        EmptyFragmentTestActivity::class.java
+    )
 
     @Test
     fun testDialogFragmentDismiss() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentTest.kt
index 6e195e3..fa776a6 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentTest.kt
@@ -32,7 +32,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -41,8 +40,11 @@
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class DialogFragmentTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule(
+        EmptyFragmentTestActivity::class.java
+    )
 
     @Test
     fun testDialogFragmentShows() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/EpicenterTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/EpicenterTest.kt
index e6a698d..d31d6be 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/EpicenterTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/EpicenterTest.kt
@@ -28,7 +28,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -39,8 +38,9 @@
 @SdkSuppress(minSdkVersion = 21) // FragmentTransitionCompat21 requires API 21
 class EpicenterTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     fun defaultEpicenter() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatedContainerTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatedContainerTest.kt
index 34b6a39..4350b4f 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatedContainerTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatedContainerTest.kt
@@ -20,7 +20,6 @@
 import androidx.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Before
@@ -33,8 +32,9 @@
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class FragmentAnimatedContainerTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Before
     fun setupContainer() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimationTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimationTest.kt
index a8599e6..9145209 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimationTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimationTest.kt
@@ -35,7 +35,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -52,8 +51,9 @@
 @RunWith(AndroidJUnit4::class)
 class FragmentAnimationTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var instrumentation: Instrumentation
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatorTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatorTest.kt
index 3886674..5808f88 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatorTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentAnimatorTest.kt
@@ -31,7 +31,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -45,8 +44,9 @@
 @RunWith(AndroidJUnit4::class)
 class FragmentAnimatorTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Before
     fun setupContainer() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentContainerViewTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentContainerViewTest.kt
index 866d69d..b025eb9e 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentContainerViewTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentContainerViewTest.kt
@@ -31,7 +31,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
@@ -46,8 +45,9 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class FragmentContainerViewTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
     lateinit var context: Context
 
     @Before
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFactoryTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFactoryTest.kt
index 28600dbb..e7fc5a7 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFactoryTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFactoryTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Rule
@@ -33,8 +32,9 @@
 @LargeTest
 class FragmentFactoryTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     private lateinit var activity: EmptyFragmentTestActivity
     private lateinit var fragmentManager: FragmentManager
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFinishEarlyTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFinishEarlyTest.kt
index a3813b7..a3f9af5 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFinishEarlyTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentFinishEarlyTest.kt
@@ -21,7 +21,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -33,8 +32,13 @@
 @LargeTest
 class FragmentFinishEarlyTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentFinishEarlyTestActivity::class.java, false, false)
+    val activityRule = androidx.test.rule.ActivityTestRule(
+        FragmentFinishEarlyTestActivity::class.java,
+        false,
+        false
+    )
 
     /**
      * FragmentActivity should not raise the state of a Fragment while it is being destroyed.
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
index 08a0cf6..d9dd33d 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
@@ -35,7 +35,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.fail
@@ -50,8 +49,9 @@
 @MediumTest
 class FragmentLifecycleTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     @Test
     fun basicLifecycle() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentManagerNonConfigTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentManagerNonConfigTest.kt
index 0c97102..1e72738 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentManagerNonConfigTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentManagerNonConfigTest.kt
@@ -21,7 +21,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.recreate
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -32,8 +31,9 @@
 @RunWith(AndroidJUnit4::class)
 class FragmentManagerNonConfigTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(NonConfigOnStopActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(NonConfigOnStopActivity::class.java)
 
     /**
      * When a fragment is added during onStop(), it shouldn't show up in non-config
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
index 5dfdb3d..c786445 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
@@ -26,7 +26,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.fail
@@ -43,8 +42,9 @@
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 class FragmentReceiveResultTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var activity: FragmentTestActivity
     private lateinit var fragment: TestFragment
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReorderingTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReorderingTest.kt
index ff2c257..c1ef8a0 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReorderingTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReorderingTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -35,8 +34,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class FragmentReorderingTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var container: ViewGroup
     private lateinit var fm: FragmentManager
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReplaceTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReplaceTest.kt
index c6bcb25..4c155a7 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReplaceTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReplaceTest.kt
@@ -20,7 +20,6 @@
 import androidx.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -32,8 +31,9 @@
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 class FragmentReplaceTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     fun testReplaceFragment() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
index 3259c33..3c802b7 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
@@ -23,7 +23,6 @@
 import androidx.savedstate.SavedStateRegistry
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.RecreatedActivity
 import androidx.testutils.recreate
 import com.google.common.truth.Truth.assertThat
@@ -35,8 +34,9 @@
 @LargeTest
 class FragmentSavedStateRegistryTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentSavedStateActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentSavedStateActivity::class.java)
 
     private fun initializeSavedState(testFragment: Fragment = Fragment()) {
         activityRule.runOnUiThread {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTest.kt
index 70b737a..4c9e7de 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
@@ -47,8 +46,9 @@
  */
 @RunWith(AndroidJUnit4::class)
 class FragmentTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var activity: FragmentTestActivity
     private lateinit var instrumentation: Instrumentation
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTestUtil.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTestUtil.kt
index 1fa9530..53624aed 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTestUtil.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTestUtil.kt
@@ -23,7 +23,6 @@
 import androidx.fragment.test.R
 import androidx.test.core.app.ActivityScenario
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertThat
@@ -31,7 +30,8 @@
 import java.lang.ref.WeakReference
 import java.util.ArrayList
 
-fun ActivityTestRule<out FragmentActivity>.executePendingTransactions(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.executePendingTransactions(
     fm: FragmentManager = activity.supportFragmentManager
 ): Boolean {
     var ret = false
@@ -45,7 +45,8 @@
     onActivity { fm.executePendingTransactions() }
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(): Boolean {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(): Boolean {
     val instrumentation = InstrumentationRegistry.getInstrumentation()
     var ret = false
     instrumentation.runOnMainSync {
@@ -54,7 +55,8 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
     id: Int,
     flags: Int = 0
 ): Boolean {
@@ -66,7 +68,8 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
     name: String,
     flags: Int = 0
 ): Boolean {
@@ -78,7 +81,10 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.setContentView(@LayoutRes layoutId: Int) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.setContentView(
+    @LayoutRes layoutId: Int
+) {
     val instrumentation = InstrumentationRegistry.getInstrumentation()
     instrumentation.runOnMainSync { activity.setContentView(layoutId) }
 }
@@ -95,16 +101,19 @@
     }
 }
 
+@Suppress("DEPRECATION")
 // Transition test methods start
-fun ActivityTestRule<out FragmentActivity>.findGreen(): View {
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findGreen(): View {
     return activity.findViewById(R.id.greenSquare)
 }
 
-fun ActivityTestRule<out FragmentActivity>.findBlue(): View {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findBlue(): View {
     return activity.findViewById(R.id.blueSquare)
 }
 
-fun ActivityTestRule<out FragmentActivity>.findRed(): View? {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findRed(): View? {
     return activity.findViewById(R.id.redSquare)
 }
 
@@ -135,20 +144,20 @@
 }
 
 fun verifyNoOtherTransitions(fragment: TransitionFragment) {
-    assertThat(fragment.enterTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.enterTransition.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.exitTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.exitTransition.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.enterTransition.enteringTargets).isEmpty()
+    assertThat(fragment.enterTransition.exitingTargets).isEmpty()
+    assertThat(fragment.exitTransition.enteringTargets).isEmpty()
+    assertThat(fragment.exitTransition.exitingTargets).isEmpty()
 
-    assertThat(fragment.reenterTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.reenterTransition.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.returnTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.returnTransition.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.reenterTransition.enteringTargets).isEmpty()
+    assertThat(fragment.reenterTransition.exitingTargets).isEmpty()
+    assertThat(fragment.returnTransition.enteringTargets).isEmpty()
+    assertThat(fragment.returnTransition.exitingTargets).isEmpty()
 
-    assertThat(fragment.sharedElementEnter.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementEnter.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementReturn.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementReturn.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.sharedElementEnter.enteringTargets).isEmpty()
+    assertThat(fragment.sharedElementEnter.exitingTargets).isEmpty()
+    assertThat(fragment.sharedElementReturn.enteringTargets).isEmpty()
+    assertThat(fragment.sharedElementReturn.exitingTargets).isEmpty()
 }
 // Transition test methods end
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
index 12aaa7d..d8040cf 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransactionTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
@@ -49,8 +48,9 @@
 @RunWith(AndroidJUnit4::class)
 class FragmentTransactionTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var activity: FragmentTestActivity
     private var onBackStackChangedTimes: Int = 0
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitTest.kt
index 641fc40..1ded023 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitTest.kt
@@ -22,7 +22,6 @@
 import androidx.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -37,8 +36,9 @@
 @RunWith(AndroidJUnit4::class)
 class FragmentTransitTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Before
     fun setupContainer() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionTest.kt
index b2aefc3..2e4d8e4 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
@@ -50,8 +49,9 @@
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
 class FragmentTransitionTest(private val reorderingAllowed: Boolean) {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private lateinit var fragmentManager: FragmentManager
@@ -361,11 +361,9 @@
             names.capture(), views.capture(),
             snapshots.capture()
         )
-        assertThat(names.value.size).isEqualTo(1)
-        assertThat(views.value.size).isEqualTo(1)
+        assertThat(names.value).containsExactly("blueSquare")
+        assertThat(views.value).containsExactly(startBlue)
         assertThat(snapshots.value).isNull()
-        assertThat(names.value[0]).isEqualTo("blueSquare")
-        assertThat(views.value[0]).isEqualTo(startBlue)
 
         val endBlue = activityRule.findBlue()
 
@@ -373,11 +371,9 @@
             names.capture(), views.capture(),
             snapshots.capture()
         )
-        assertThat(names.value.size).isEqualTo(1)
-        assertThat(views.value.size).isEqualTo(1)
+        assertThat(names.value).containsExactly("blueSquare")
+        assertThat(views.value).containsExactly(endBlue)
         assertThat(snapshots.value).isNull()
-        assertThat(names.value[0]).isEqualTo("blueSquare")
-        assertThat(views.value[0]).isEqualTo(endBlue)
 
         // Now pop the back stack
         reset(enterCallback)
@@ -387,11 +383,9 @@
             names.capture(), views.capture(),
             snapshots.capture()
         )
-        assertThat(names.value.size).isEqualTo(1)
-        assertThat(views.value.size).isEqualTo(1)
+        assertThat(names.value).containsExactly("blueSquare")
+        assertThat(views.value).containsExactly(endBlue)
         assertThat(snapshots.value).isNull()
-        assertThat(names.value[0]).isEqualTo("blueSquare")
-        assertThat(views.value[0]).isEqualTo(endBlue)
 
         val reenterBlue = activityRule.findBlue()
 
@@ -399,11 +393,9 @@
             names.capture(), views.capture(),
             snapshots.capture()
         )
-        assertThat(names.value.size).isEqualTo(1)
-        assertThat(views.value.size).isEqualTo(1)
+        assertThat(names.value).containsExactly("blueSquare")
+        assertThat(views.value).containsExactly(reenterBlue)
         assertThat(snapshots.value).isNull()
-        assertThat(names.value[0]).isEqualTo("blueSquare")
-        assertThat(views.value[0]).isEqualTo(reenterBlue)
     }
 
     // Make sure that onMapSharedElement works to change the shared element going out
@@ -424,10 +416,8 @@
                 names: List<String>,
                 sharedElements: MutableMap<String, View>
             ) {
-                assertThat(names.size).isEqualTo(1)
-                assertThat(names[0]).isEqualTo("blueSquare")
-                assertThat(sharedElements.size).isEqualTo(1)
-                assertThat(sharedElements["blueSquare"]).isEqualTo(startBlue)
+                assertThat(names).containsExactly("blueSquare")
+                assertThat(sharedElements).containsExactly("blueSquare", startBlue)
                 sharedElements["blueSquare"] = startGreen
             }
         }
@@ -458,11 +448,9 @@
                 names: List<String>,
                 sharedElements: MutableMap<String, View>
             ) {
-                assertThat(names.size).isEqualTo(1)
-                assertThat(names[0]).isEqualTo("blueSquare")
-                assertThat(sharedElements.size).isEqualTo(1)
+                assertThat(names).containsExactly("blueSquare")
                 val expectedBlue = findViewById(fragment1, R.id.blueSquare)
-                assertThat(sharedElements["blueSquare"]).isEqualTo(expectedBlue)
+                assertThat(sharedElements).containsExactly("blueSquare", expectedBlue)
                 val greenSquare = findViewById(fragment1, R.id.greenSquare)
                 sharedElements["blueSquare"] = greenSquare
             }
@@ -498,11 +486,9 @@
                 names: List<String>,
                 sharedElements: MutableMap<String, View>
             ) {
-                assertThat(names.size).isEqualTo(1)
-                assertThat(names[0]).isEqualTo("blueSquare")
-                assertThat(sharedElements.size).isEqualTo(1)
+                assertThat(names).containsExactly("blueSquare")
                 val blueSquare = findViewById(fragment2, R.id.blueSquare)
-                assertThat(sharedElements["blueSquare"]).isEqualTo(blueSquare)
+                assertThat(sharedElements).containsExactly("blueSquare", blueSquare)
                 val greenSquare = findViewById(fragment2, R.id.greenSquare)
                 sharedElements["blueSquare"] = greenSquare
             }
@@ -535,10 +521,8 @@
                 names: List<String>,
                 sharedElements: MutableMap<String, View>
             ) {
-                assertThat(names.size).isEqualTo(1)
-                assertThat(names[0]).isEqualTo("blueSquare")
-                assertThat(sharedElements.size).isEqualTo(1)
-                assertThat(sharedElements["blueSquare"]).isEqualTo(endBlue)
+                assertThat(names).containsExactly("blueSquare")
+                assertThat(sharedElements).containsExactly("blueSquare", endBlue)
                 sharedElements["blueSquare"] = endGreen
             }
         }
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
index fc91326..00ea701 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
@@ -34,7 +34,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.fail
@@ -51,8 +50,9 @@
 @LargeTest
 class FragmentViewLifecycleTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     @UiThreadTest
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt
index 7a709e8c..941aefa 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.fail
@@ -36,8 +35,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class FragmentViewTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/HangingFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/HangingFragmentTest.kt
index f69379b..4796cac 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/HangingFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/HangingFragmentTest.kt
@@ -19,7 +19,6 @@
 import androidx.fragment.app.test.HangingFragmentActivity
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.recreate
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -30,8 +29,9 @@
 @MediumTest
 class HangingFragmentTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(HangingFragmentActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(HangingFragmentActivity::class.java)
 
     @Test
     fun testNoCrash() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
index 8ed6f9b..c0e7750 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.recreate
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
@@ -37,8 +36,9 @@
 @RunWith(AndroidJUnit4::class)
 @MediumTest
 class LoaderTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(LoaderActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(LoaderActivity::class.java)
 
     /**
      * Test to ensure that there is no Activity leak due to Loader
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentRestoreTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentRestoreTest.kt
index 2e066fb..d0cf2b1 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentRestoreTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentRestoreTest.kt
@@ -21,11 +21,11 @@
 import androidx.fragment.app.test.FragmentTestActivity
 import androidx.fragment.app.test.FragmentTestActivity.ParentFragment
 import androidx.fragment.test.R
+import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
+import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertWithMessage
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.util.concurrent.CountDownLatch
@@ -35,67 +35,69 @@
 @RunWith(AndroidJUnit4::class)
 class NestedFragmentRestoreTest {
 
-    @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
-
+    @Suppress("DEPRECATION")
     @Test
     fun recreateActivity() {
-        val activity = activityRule.activity
-        activityRule.runOnUiThread {
-            val parent = ParentFragment()
-            parent.retainChildInstance = true
+        with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            val activity = withActivity {
+                val parent = ParentFragment()
+                parent.retainChildInstance = true
 
-            activity.supportFragmentManager.beginTransaction()
-                .add(parent, "parent")
-                .commitNow()
+                supportFragmentManager.beginTransaction()
+                    .add(parent, "parent")
+                    .commitNow()
+
+                this
+            }
+
+            val fm = withActivity { supportFragmentManager }
+            val parent = fm.findFragmentByTag("parent") as ParentFragment
+            val child = parent.childFragment
+
+            var attachedTo: Context? = null
+            val latch = CountDownLatch(1)
+            child.onAttachListener = { context ->
+                attachedTo = context
+                latch.countDown()
+            }
+
+            recreate()
+
+            assertWithMessage("timeout waiting for recreate")
+                .that(latch.await(10, TimeUnit.SECONDS))
+                .isTrue()
+
+            assertWithMessage("attached as part of recreate").that(attachedTo).isNotNull()
+            assertWithMessage("attached to new context")
+                .that(attachedTo)
+                .isNotSameInstanceAs(activity)
+            assertWithMessage("attached to new parent fragment")
+                .that(child)
+                .isNotSameInstanceAs(parent)
         }
-
-        val fm = activity.supportFragmentManager
-        val parent = fm.findFragmentByTag("parent") as ParentFragment
-        val child = parent.childFragment
-
-        var attachedTo: Context? = null
-        val latch = CountDownLatch(1)
-        child.onAttachListener = { context ->
-            attachedTo = context
-            latch.countDown()
-        }
-
-        activityRule.runOnUiThread { activity.recreate() }
-
-        assertWithMessage("timeout waiting for recreate")
-            .that(latch.await(10, TimeUnit.SECONDS))
-            .isTrue()
-
-        assertWithMessage("attached as part of recreate").that(attachedTo).isNotNull()
-        assertWithMessage("attached to new context")
-            .that(attachedTo)
-            .isNotSameInstanceAs(activity)
-        assertWithMessage("attached to new parent fragment")
-            .that(child)
-            .isNotSameInstanceAs(parent)
     }
 
     @Test
     fun restoreViewStateTest() {
-        val activity = activityRule.activity
-        activityRule.runOnUiThread {
-            val parent = RestoreViewParentFragment()
+        with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            withActivity {
+                val parent = RestoreViewParentFragment()
 
-            activity.supportFragmentManager.beginTransaction()
-                .add(parent, "parent")
-                .commitNow()
+                supportFragmentManager.beginTransaction()
+                    .add(parent, "parent")
+                    .commitNow()
+            }
+
+            recreate()
+
+            val fm = withActivity { supportFragmentManager }
+            val parent = fm.findFragmentByTag("parent") as RestoreViewParentFragment
+            val child = parent.childFragment
+
+            assertWithMessage("parent view was restored before child")
+                .that(child.viewRestoredAfterParent)
+                .isTrue()
         }
-
-        activityRule.runOnUiThread { activity.recreate() }
-
-        val fm = activity.supportFragmentManager
-        val parent = fm.findFragmentByTag("parent") as RestoreViewParentFragment
-        val child = parent.childFragment
-
-        assertWithMessage("parent view was restored before child")
-            .that(child.viewRestoredAfterParent)
-            .isTrue()
     }
 }
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentTest.kt
index 74321c2..900fe1f 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedFragmentTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -38,8 +37,9 @@
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class NestedFragmentTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private lateinit var instrumentation: Instrumentation
     private lateinit var parentFragment: ParentFragment
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedInflatedFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedInflatedFragmentTest.kt
index 5079734..fad78f7 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedInflatedFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/NestedInflatedFragmentTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -37,8 +36,9 @@
 @MediumTest
 class NestedInflatedFragmentTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     @UiThreadTest
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OptionsMenuFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OptionsMenuFragmentTest.kt
index 7ac49b6..1775a46 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OptionsMenuFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OptionsMenuFragmentTest.kt
@@ -26,7 +26,6 @@
 import androidx.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -36,8 +35,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class OptionsMenuFragmentTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @Test
     fun fragmentWithOptionsMenu() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PostponedTransitionTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PostponedTransitionTest.kt
index 32970d6..f5cb7ba 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PostponedTransitionTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PostponedTransitionTest.kt
@@ -28,7 +28,6 @@
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
@@ -45,8 +44,9 @@
 @RunWith(AndroidJUnit4::class)
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
 class PostponedTransitionTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private val beginningFragment = PostponedFragment1()
@@ -1159,12 +1159,12 @@
     }
 
     private fun assertNoTargets(fragment: TransitionFragment) {
-        assertThat(fragment.enterTransition.targets.isEmpty()).isTrue()
-        assertThat(fragment.reenterTransition.targets.isEmpty()).isTrue()
-        assertThat(fragment.exitTransition.targets.isEmpty()).isTrue()
-        assertThat(fragment.returnTransition.targets.isEmpty()).isTrue()
-        assertThat(fragment.sharedElementEnter.targets.isEmpty()).isTrue()
-        assertThat(fragment.sharedElementReturn.targets.isEmpty()).isTrue()
+        assertThat(fragment.enterTransition.targets).isEmpty()
+        assertThat(fragment.reenterTransition.targets).isEmpty()
+        assertThat(fragment.exitTransition.targets).isEmpty()
+        assertThat(fragment.returnTransition.targets).isEmpty()
+        assertThat(fragment.sharedElementEnter.targets).isEmpty()
+        assertThat(fragment.sharedElementReturn.targets).isEmpty()
     }
 
     open class PostponedFragment1 : TransitionFragment(R.layout.scene1) {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PrimaryNavFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PrimaryNavFragmentTest.kt
index 047de56..42d4377 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PrimaryNavFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PrimaryNavFragmentTest.kt
@@ -23,7 +23,6 @@
 import androidx.fragment.app.test.EmptyFragmentTestActivity
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
@@ -35,8 +34,9 @@
 @RunWith(AndroidJUnit4::class)
 @LargeTest
 class PrimaryNavFragmentTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     @Test
     fun delegateBackToPrimaryNav() {
@@ -346,7 +346,9 @@
         activityRule.runOnUiThread { fm.executePendingTransactions() }
     }
 
-    private fun ActivityTestRule<out Activity>.onBackPressed() = runOnUiThreadRethrow {
+    @Suppress("DEPRECATION")
+    private fun androidx.test.rule.ActivityTestRule<out Activity>.onBackPressed() =
+        runOnUiThreadRethrow {
         activity.onBackPressed()
     }
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ReentrantFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ReentrantFragmentTest.kt
index 2fd0970..681023d 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ReentrantFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ReentrantFragmentTest.kt
@@ -21,7 +21,6 @@
 import androidx.fragment.app.test.EmptyFragmentTestActivity
 import androidx.lifecycle.ViewModelStore
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.fail
 import org.junit.Rule
@@ -50,8 +49,9 @@
         }
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     // Make sure that executing transactions during activity lifecycle events
     // is properly prevented.
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt
index 366d00c..8b58e97 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
@@ -35,8 +34,11 @@
 @LargeTest
 class SafeTransactionInOnResumeTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule<OnResumeTestActivity>(OnResumeTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule<OnResumeTestActivity>(
+        OnResumeTestActivity::class.java
+    )
 
     @Test
     @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.M)
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveStateFragmentTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveStateFragmentTest.kt
index 5a41174..ee22624 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveStateFragmentTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveStateFragmentTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
@@ -36,8 +35,9 @@
 @MediumTest
 class SaveStateFragmentTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     @Test
     @UiThreadTest
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/TargetFragmentLifeCycleTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/TargetFragmentLifeCycleTest.kt
index aef943b..768f598 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/TargetFragmentLifeCycleTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/TargetFragmentLifeCycleTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert
@@ -35,8 +34,9 @@
 @MediumTest
 class TargetFragmentLifeCycleTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     @Test
     fun targetFragmentNoCycles() {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/UserVisibleHintTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/UserVisibleHintTest.kt
index 7108710..14b4071 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/UserVisibleHintTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/UserVisibleHintTest.kt
@@ -20,7 +20,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
@@ -32,8 +31,9 @@
 @MediumTest
 class UserVisibleHintTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(FragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(FragmentTestActivity::class.java)
 
     @UiThreadTest
     @Test
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ViewModelTestInTransaction.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ViewModelTestInTransaction.kt
index f281002..9809d911 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ViewModelTestInTransaction.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ViewModelTestInTransaction.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -33,8 +32,9 @@
 @RunWith(AndroidJUnit4::class)
 class ViewModelTestInTransaction {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmptyFragmentTestActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyFragmentTestActivity::class.java)
 
     @Test
     @UiThreadTest
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
index 16448d8..52f6d3b 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
@@ -102,12 +102,9 @@
                     }
                     break;
                 case ADD:
-                    // To transition from the firstOut to the lastIn, we need
-                    // the firstOut operation to occur first. Only after that
-                    // is set do we set the lastIn
-                    if (firstOut != null) {
-                        lastIn = operation;
-                    }
+                    // The last ADD is, by definition, the lastIn Operation
+                    lastIn = operation;
+                    break;
             }
         }
 
@@ -269,30 +266,67 @@
         final Rect lastInEpicenterRect = new Rect();
         ArrayList<View> sharedElementFirstOutViews = new ArrayList<>();
         ArrayList<View> sharedElementLastInViews = new ArrayList<>();
+        ArrayMap<String, String> sharedElementNameMapping = new ArrayMap<>();
         for (final TransitionInfo transitionInfo : transitionInfos) {
             boolean hasSharedElementTransition = transitionInfo.hasSharedElementTransition();
-            if (hasSharedElementTransition) {
-                sharedElementTransition = transitionImpl.cloneTransition(
-                        transitionInfo.getSharedElementTransition());
+            // Compute the shared element transition between the firstOut and lastIn Fragments
+            if (hasSharedElementTransition && firstOut != null && lastIn != null) {
+                // swapSharedElementTargets requires wrapping this in a TransitionSet
+                sharedElementTransition = transitionImpl.wrapTransitionInSet(
+                        transitionImpl.cloneTransition(
+                                transitionInfo.getSharedElementTransition()));
                 Fragment sharedElementFragment = transitionInfo.getOperation().getFragment();
-                // A pop means returning from the target names to the source names
-                // so we have to swap the source/target sets
-                ArrayList<String> enteringNames = isPop
-                        ? sharedElementFragment.getSharedElementTargetNames()
-                        : sharedElementFragment.getSharedElementSourceNames();
-                ArrayList<String> exitingNames = isPop
-                        ? sharedElementFragment.getSharedElementSourceNames()
-                        : sharedElementFragment.getSharedElementTargetNames();
-                if (firstOut != null) {
-                    // Capture all of the Views from the firstOut fragment that are
-                    // part of the shared element transition
-                    ArrayMap<String, View> firstOutViews = new ArrayMap<>();
-                    findNamedViews(firstOutViews, firstOut.getFragment().mView);
-                    // TODO call through to onMapSharedElements
-                    firstOutViews.retainAll(exitingNames);
+                ArrayList<String> exitingNames;
+                ArrayList<String> enteringNames;
+                if (!isPop) {
+                    // Forward transitions have the source shared elements exiting
+                    // and the target shared elements entering
+                    exitingNames = sharedElementFragment.getSharedElementSourceNames();
+                    enteringNames = sharedElementFragment.getSharedElementTargetNames();
+                } else {
+                    // A pop is the reverse: the target elements are now the ones exiting
+                    // and the source shared elements are entering
+                    exitingNames = sharedElementFragment.getSharedElementTargetNames();
+                    enteringNames = sharedElementFragment.getSharedElementSourceNames();
+                }
+                int numSharedElements = exitingNames.size();
+                for (int i = 0; i < numSharedElements; i++) {
+                    String exitingName = exitingNames.get(i);
+                    String enteringName = enteringNames.get(i);
+                    sharedElementNameMapping.put(exitingName, enteringName);
+                }
 
-                    // Find all views under the shared element views and add them
-                    // to the shared element transition
+                // Find all of the Views from the firstOut fragment that are
+                // part of the shared element transition
+                ArrayMap<String, View> firstOutViews = new ArrayMap<>();
+                findNamedViews(firstOutViews, firstOut.getFragment().mView);
+                // TODO call through to onMapSharedElements
+                firstOutViews.retainAll(exitingNames);
+                // Only keep the mapping of elements that were found in the firstOut Fragment
+                sharedElementNameMapping.retainAll(firstOutViews.keySet());
+
+                // Find all of the Views from the lastIn fragment that are
+                // part of the shared element transition
+                ArrayMap<String, View> lastInViews = new ArrayMap<>();
+                findNamedViews(lastInViews, lastIn.getFragment().mView);
+                // TODO call through to onMapSharedElements
+                lastInViews.retainAll(enteringNames);
+                // Only keep the mapping of elements that were found in the lastIn Fragment
+                FragmentTransition.retainValues(sharedElementNameMapping, lastInViews);
+
+                // Now make a final pass through the Views list to ensure they
+                // don't still have elements that were removed from the mapping
+                firstOutViews.retainAll(sharedElementNameMapping.keySet());
+                lastInViews.retainAll(sharedElementNameMapping.values());
+
+                if (sharedElementNameMapping.isEmpty()) {
+                    // We couldn't find any valid shared element mappings, so clear out
+                    // the shared element transition information entirely
+                    sharedElementTransition = null;
+                    sharedElementFirstOutViews.clear();
+                    sharedElementLastInViews.clear();
+                } else {
+                    // Capture all views from the firstOut Fragment under the shared element views
                     for (View sharedElementView : firstOutViews.values()) {
                         captureTransitioningViews(sharedElementFirstOutViews,
                                 sharedElementView);
@@ -305,23 +339,14 @@
                         transitionImpl.setEpicenter(sharedElementTransition,
                                 firstOutEpicenterView);
                     }
-                }
-                if (lastIn != null) {
-                    // Capture all of the Views from the lastIn fragment that are
-                    // part of the shared element transition
-                    ArrayMap<String, View> lastInViews = new ArrayMap<>();
-                    findNamedViews(lastInViews, lastIn.getFragment().mView);
-                    // TODO call through to onMapSharedElements
-                    lastInViews.retainAll(enteringNames);
 
-                    // Find all views under the shared element views and add them
-                    // to the shared element transition
+                    // Capture all views from the lastIn Fragment under the shared element views
                     for (View sharedElementView : lastInViews.values()) {
                         captureTransitioningViews(sharedElementLastInViews,
                                 sharedElementView);
                     }
 
-                    // Compute the epicenter of the firstOut transition
+                    // Compute the epicenter of the lastIn transition
                     if (!enteringNames.isEmpty()) {
                         String epicenterViewName = enteringNames.get(0);
                         final View lastInEpicenterView = lastInViews.get(epicenterViewName);
@@ -340,13 +365,12 @@
                             });
                         }
                     }
+
+                    // Now set the transition's targets to only the firstOut Fragment's views
+                    // It'll be swapped to the lastIn Fragment's views after the
+                    // transition is started
+                    transitionImpl.addTargets(sharedElementTransition, sharedElementFirstOutViews);
                 }
-                // Now set the transition's targets
-                ArrayList<View> sharedElementTargets = new ArrayList<>();
-                sharedElementTargets.add(nonExistentView);
-                sharedElementTargets.addAll(sharedElementFirstOutViews);
-                sharedElementTargets.addAll(sharedElementLastInViews);
-                transitionImpl.addTargets(sharedElementTransition, sharedElementTargets);
             }
         }
         ArrayList<View> enteringViews = new ArrayList<>();
@@ -382,7 +406,11 @@
                         transitioningViews.removeAll(sharedElementLastInViews);
                     }
                 }
-                transitionImpl.addTargets(transition, transitioningViews);
+                if (transitioningViews.isEmpty()) {
+                    transitionImpl.addTarget(transition, nonExistentView);
+                } else {
+                    transitionImpl.addTargets(transition, transitioningViews);
+                }
                 if (transitionInfo.getOperation().getType().equals(Operation.Type.ADD)) {
                     enteringViews.addAll(transitioningViews);
                     if (hasLastInEpicenter) {
@@ -430,11 +458,17 @@
         // First, hide all of the entering views so they're in
         // the correct initial state
         FragmentTransition.setViewVisibility(enteringViews, View.INVISIBLE);
+        ArrayList<String> inNames =
+                transitionImpl.prepareSetNameOverridesReordered(sharedElementLastInViews);
         // Now actually start the transition
         transitionImpl.beginDelayedTransition(getContainer(), mergedTransition);
+        transitionImpl.setNameOverridesReordered(getContainer(), sharedElementFirstOutViews,
+                sharedElementLastInViews, inNames, sharedElementNameMapping);
         // Then, show all of the entering views, putting them into
         // the correct final state
         FragmentTransition.setViewVisibility(enteringViews, View.VISIBLE);
+        transitionImpl.swapSharedElementTargets(sharedElementTransition,
+                sharedElementFirstOutViews, sharedElementLastInViews);
     }
 
     /**
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
index 4af21ba..fdd94b7 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
@@ -501,7 +501,24 @@
             if (mFragment.mHidden) {
                 mFragment.mView.setVisibility(View.GONE);
             }
-            ViewCompat.requestApplyInsets(mFragment.mView);
+            // How I wish we could use doOnAttach
+            if (ViewCompat.isAttachedToWindow(mFragment.mView)) {
+                ViewCompat.requestApplyInsets(mFragment.mView);
+            } else {
+                final View fragmentView = mFragment.mView;
+                fragmentView.addOnAttachStateChangeListener(
+                        new View.OnAttachStateChangeListener() {
+                            @Override
+                            public void onViewAttachedToWindow(View v) {
+                                fragmentView.removeOnAttachStateChangeListener(this);
+                                ViewCompat.requestApplyInsets(fragmentView);
+                            }
+
+                            @Override
+                            public void onViewDetachedFromWindow(View v) {
+                            }
+                        });
+            }
             mFragment.onViewCreated(mFragment.mView, mFragment.mSavedFragmentState);
             mDispatcher.dispatchOnFragmentViewCreated(
                     mFragment, mFragment.mView, mFragment.mSavedFragmentState, false);
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransition.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransition.java
index e8c184e..10ede0f 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransition.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransition.java
@@ -1002,8 +1002,8 @@
      * that has a key in {@code namedViews}. This is a useful equivalent to
      * {@link ArrayMap#retainAll(Collection)} for values.
      */
-    private static void retainValues(ArrayMap<String, String> nameOverrides,
-            ArrayMap<String, View> namedViews) {
+    static void retainValues(@NonNull ArrayMap<String, String> nameOverrides,
+            @NonNull ArrayMap<String, View> namedViews) {
         for (int i = nameOverrides.size() - 1; i >= 0; i--) {
             final String targetName = nameOverrides.valueAt(i);
             if (!namedViews.containsKey(targetName)) {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 820c319..72af725a 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-6.4-bin.zip
+distributionUrl=../../../../tools/external/gradle/gradle-6.5-bin.zip
diff --git a/gridlayout/gridlayout/api/res-1.0.0.txt b/gridlayout/gridlayout/api/res-1.0.0.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gridlayout/gridlayout/api/res-1.0.0.txt
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index 75b29a9..f3371e7 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -493,6 +493,14 @@
       "to": "ignore"
     },
     {
+      "from": "androidx/wear/input/(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/wear/input/testing/(.*)",
+      "to": "ignore"
+    },
+    {
       "from": "androidx/benchmark/(.*)",
       "to": "ignore"
     },
@@ -1107,6 +1115,14 @@
       "to": "androidx/wear"
     },
     {
+      "from": "androidx/wear/input",
+      "to": "androidx/wear/input"
+    },
+    {
+      "from": "androidx/wear/input/testing",
+      "to": "androidx/wear/input/testing"
+    },
+    {
       "from": "androidx/emoji/appcompat",
       "to": "androidx/emoji/appcompat"
     },
@@ -2066,6 +2082,30 @@
     },
     {
       "from": {
+        "groupId": "androidx.wear",
+        "artifactId": "wear-input",
+        "version": "{newSlVersion}"
+      },
+      "to": {
+        "groupId": "androidx.wear",
+        "artifactId": "wear-input",
+        "version": "{newSlVersion}"
+      }
+    },
+    {
+      "from": {
+        "groupId": "androidx.wear",
+        "artifactId": "wear-input-testing",
+        "version": "{newSlVersion}"
+      },
+      "to": {
+        "groupId": "androidx.wear",
+        "artifactId": "wear-input-testing",
+        "version": "{newSlVersion}"
+      }
+    },
+    {
+      "from": {
         "groupId": "androidx.asynclayoutinflater",
         "artifactId": "asynclayoutinflater",
         "version": "{newSlVersion}"
diff --git a/lifecycle/lifecycle-common-java8/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-common-java8/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..498d3a9
--- /dev/null
+++ b/lifecycle/lifecycle-common-java8/api/2.3.0-alpha04.txt
@@ -0,0 +1,14 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public interface DefaultLifecycleObserver extends androidx.lifecycle.LifecycleObserver androidx.lifecycle.LifecycleObserver {
+    method public default void onCreate(androidx.lifecycle.LifecycleOwner);
+    method public default void onDestroy(androidx.lifecycle.LifecycleOwner);
+    method public default void onPause(androidx.lifecycle.LifecycleOwner);
+    method public default void onResume(androidx.lifecycle.LifecycleOwner);
+    method public default void onStart(androidx.lifecycle.LifecycleOwner);
+    method public default void onStop(androidx.lifecycle.LifecycleOwner);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-common-java8/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-common-java8/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..498d3a9
--- /dev/null
+++ b/lifecycle/lifecycle-common-java8/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,14 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public interface DefaultLifecycleObserver extends androidx.lifecycle.LifecycleObserver androidx.lifecycle.LifecycleObserver {
+    method public default void onCreate(androidx.lifecycle.LifecycleOwner);
+    method public default void onDestroy(androidx.lifecycle.LifecycleOwner);
+    method public default void onPause(androidx.lifecycle.LifecycleOwner);
+    method public default void onResume(androidx.lifecycle.LifecycleOwner);
+    method public default void onStart(androidx.lifecycle.LifecycleOwner);
+    method public default void onStop(androidx.lifecycle.LifecycleOwner);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-common-java8/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-common-java8/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..498d3a9
--- /dev/null
+++ b/lifecycle/lifecycle-common-java8/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,14 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public interface DefaultLifecycleObserver extends androidx.lifecycle.LifecycleObserver androidx.lifecycle.LifecycleObserver {
+    method public default void onCreate(androidx.lifecycle.LifecycleOwner);
+    method public default void onDestroy(androidx.lifecycle.LifecycleOwner);
+    method public default void onPause(androidx.lifecycle.LifecycleOwner);
+    method public default void onResume(androidx.lifecycle.LifecycleOwner);
+    method public default void onStart(androidx.lifecycle.LifecycleOwner);
+    method public default void onStop(androidx.lifecycle.LifecycleOwner);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-common/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-common/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..3f2e1d7
--- /dev/null
+++ b/lifecycle/lifecycle-common/api/2.3.0-alpha04.txt
@@ -0,0 +1,46 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class Lifecycle {
+    ctor public Lifecycle();
+    method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver);
+  }
+
+  public enum Lifecycle.Event {
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_PAUSE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_RESUME;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_START;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_STOP;
+  }
+
+  public enum Lifecycle.State {
+    method public boolean isAtLeast(androidx.lifecycle.Lifecycle.State);
+    enum_constant public static final androidx.lifecycle.Lifecycle.State CREATED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State DESTROYED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State INITIALIZED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State RESUMED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State STARTED;
+  }
+
+  public interface LifecycleEventObserver extends androidx.lifecycle.LifecycleObserver {
+    method public void onStateChanged(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.Event);
+  }
+
+  public interface LifecycleObserver {
+  }
+
+  public interface LifecycleOwner {
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface OnLifecycleEvent {
+    method public abstract androidx.lifecycle.Lifecycle.Event! value();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..3f2e1d7
--- /dev/null
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,46 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class Lifecycle {
+    ctor public Lifecycle();
+    method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver);
+  }
+
+  public enum Lifecycle.Event {
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_PAUSE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_RESUME;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_START;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_STOP;
+  }
+
+  public enum Lifecycle.State {
+    method public boolean isAtLeast(androidx.lifecycle.Lifecycle.State);
+    enum_constant public static final androidx.lifecycle.Lifecycle.State CREATED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State DESTROYED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State INITIALIZED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State RESUMED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State STARTED;
+  }
+
+  public interface LifecycleEventObserver extends androidx.lifecycle.LifecycleObserver {
+    method public void onStateChanged(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.Event);
+  }
+
+  public interface LifecycleObserver {
+  }
+
+  public interface LifecycleOwner {
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface OnLifecycleEvent {
+    method public abstract androidx.lifecycle.Lifecycle.Event! value();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..0a6849f
--- /dev/null
+++ b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,62 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface GeneratedAdapter {
+    method public void callMethods(androidx.lifecycle.LifecycleOwner!, androidx.lifecycle.Lifecycle.Event!, boolean, androidx.lifecycle.MethodCallsLogger!);
+  }
+
+  @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface GenericLifecycleObserver extends androidx.lifecycle.LifecycleEventObserver {
+  }
+
+  public abstract class Lifecycle {
+    ctor public Lifecycle();
+    method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver);
+  }
+
+  public enum Lifecycle.Event {
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_PAUSE;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_RESUME;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_START;
+    enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_STOP;
+  }
+
+  public enum Lifecycle.State {
+    method public boolean isAtLeast(androidx.lifecycle.Lifecycle.State);
+    enum_constant public static final androidx.lifecycle.Lifecycle.State CREATED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State DESTROYED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State INITIALIZED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State RESUMED;
+    enum_constant public static final androidx.lifecycle.Lifecycle.State STARTED;
+  }
+
+  public interface LifecycleEventObserver extends androidx.lifecycle.LifecycleObserver {
+    method public void onStateChanged(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.Event);
+  }
+
+  public interface LifecycleObserver {
+  }
+
+  public interface LifecycleOwner {
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class Lifecycling {
+    method public static String! getAdapterName(String!);
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class MethodCallsLogger {
+    ctor public MethodCallsLogger();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public boolean approveCall(String!, int);
+  }
+
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface OnLifecycleEvent {
+    method public abstract androidx.lifecycle.Lifecycle.Event! value();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
index 2a1a5f5..3a7be4e 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
@@ -37,6 +37,8 @@
     }
     compileOnly KOTLIN_STDLIB
 
+    compileOnly LINT_CORE
+
     testImplementation KOTLIN_STDLIB
     testImplementation LINT_CORE
     testImplementation LINT_TESTS
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
index 10a133f..2bb57da 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
@@ -16,6 +16,7 @@
 
 package androidx.lifecycle.lint
 
+import com.android.tools.lint.checks.DataFlowAnalyzer
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
@@ -38,8 +39,10 @@
 import org.jetbrains.uast.UClass
 import org.jetbrains.uast.UElement
 import org.jetbrains.uast.UReferenceExpression
+import org.jetbrains.uast.getParentOfType
 import org.jetbrains.uast.getUastParentOfType
 import org.jetbrains.uast.isNullLiteral
+import org.jetbrains.uast.kotlin.KotlinUField
 import org.jetbrains.uast.kotlin.KotlinUSimpleReferenceExpression
 import org.jetbrains.uast.resolveToUElement
 
@@ -77,16 +80,38 @@
         if (!isKotlin(node.sourcePsi) || !context.evaluator.isMemberInSubClassOf(method,
                 "androidx.lifecycle.LiveData", false)) return
 
+        val fieldTypes = mutableListOf<KtTypeReference>()
+
+        val analyzer = node.getParentOfType<UClass>(UClass::class.java, true) ?: return
+        analyzer.accept(object : DataFlowAnalyzer(listOf(node)) {
+            override fun visitClass(node: UClass): Boolean {
+                for (element in node.uastDeclarations) {
+                    if (element is KotlinUField) {
+                        (element.sourcePsi?.children?.get(0) as? KtCallExpression)
+                            ?.typeArguments?.singleOrNull()?.typeReference?.let {
+                            fieldTypes.add(it)
+                        }
+                    }
+                }
+                return super.visitClass(node)
+            }
+        })
+
         val receiverType = node.receiverType as PsiClassType
-        val liveDataType = if (receiverType.hasParameters()) {
-            val receiver = (node.receiver as? KotlinUSimpleReferenceExpression)?.resolve() ?: return
-            val assignment = UastLintUtils.findLastAssignment(receiver as PsiVariable, node)
-                ?: return
-            val constructorExpression = assignment.sourcePsi as? KtCallExpression
-            constructorExpression?.typeArguments?.singleOrNull()?.typeReference
+        val liveDataType = if (fieldTypes.isNullOrEmpty()) {
+            if (receiverType.hasParameters()) {
+                val receiver =
+                    (node.receiver as? KotlinUSimpleReferenceExpression)?.resolve() ?: return
+                val assignment = UastLintUtils.findLastAssignment(receiver as PsiVariable, node)
+                    ?: return
+                val constructorExpression = assignment.sourcePsi as? KtCallExpression
+                constructorExpression?.typeArguments?.singleOrNull()?.typeReference
+            } else {
+                getTypeArg(receiverType)
+            } ?: return
         } else {
-            getTypeArg(receiverType)
-        } ?: return
+            fieldTypes[0]
+        }
 
         if (liveDataType.typeElement !is KtNullableType) {
             val fixes = mutableListOf<LintFix>()
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetectorTest.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetectorTest.kt
index 9094fd1..2f5cd03 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetectorTest.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetectorTest.kt
@@ -128,6 +128,114 @@
     }
 
     @Test
+    fun nullLiteralFailField() {
+        check(
+            kotlin(
+                """
+                package com.example
+
+                import androidx.lifecycle.MutableLiveData
+
+                val liveDataField = MutableLiveData<Boolean>()
+
+                fun foo() {
+                    liveDataField.value = null
+                }
+            """
+            ).indented()
+        ).expect("""
+src/com/example/test.kt:8: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    liveDataField.value = null
+                          ~~~~
+1 errors, 0 warnings
+        """)
+    }
+
+    @Test
+    fun nullLiteralFailMultipleFields() {
+        check(
+            kotlin(
+                """
+                package com.example
+
+                import androidx.lifecycle.MutableLiveData
+
+                val liveDataField = MutableLiveData<Boolean>()
+                val secondLiveDataField = MutableLiveData<String>()
+
+                fun foo() {
+                    liveDataField.value = null
+                    secondLiveDataField.value = null
+                }
+            """
+            ).indented()
+        ).expect("""
+src/com/example/test.kt:9: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    liveDataField.value = null
+                          ~~~~
+src/com/example/test.kt:10: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    secondLiveDataField.value = null
+                                ~~~~
+2 errors, 0 warnings
+        """)
+    }
+
+    @Test
+    fun nullLiteralFailFieldAndIgnore() {
+        check(
+            kotlin(
+                """
+                package com.example
+
+                import androidx.lifecycle.MutableLiveData
+
+                val liveDataField = MutableLiveData<Boolean>()
+                val ignoreThisField = ArrayList<String>(arrayListOf("a", "b"))
+
+                fun foo() {
+                    liveDataField.value = null
+                    ignoreThisField[0] = null
+                }
+            """
+            ).indented()
+        ).expect("""
+src/com/example/test.kt:9: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    liveDataField.value = null
+                          ~~~~
+1 errors, 0 warnings
+        """)
+    }
+
+    @Test
+    fun nullLiteralFailFieldAndLocalVariable() {
+        check(
+            kotlin(
+                """
+                package com.example
+
+                import androidx.lifecycle.MutableLiveData
+
+                val liveDataField = MutableLiveData<Boolean>()
+
+                fun foo() {
+                    liveDataField.value = null
+                    val liveDataVariable = MutableLiveData<Boolean>()
+                    liveDataVariable.value = null
+                }
+            """
+            ).indented()
+        ).expect("""
+src/com/example/test.kt:8: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    liveDataField.value = null
+                          ~~~~
+src/com/example/test.kt:10: Error: Cannot set non-nullable LiveData value to null [NullSafeMutableLiveData]
+    liveDataVariable.value = null
+                             ~~~~
+2 errors, 0 warnings
+        """)
+    }
+
+    @Test
     fun nullLiteralQuickFix() {
         check(
             kotlin("""
diff --git a/lifecycle/lifecycle-livedata-core-ktx/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core-ktx/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..b1e79f4
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core-ktx/api/2.3.0-alpha04.txt
@@ -0,0 +1,9 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataKt {
+    method @MainThread public static inline <T> androidx.lifecycle.Observer<T> observe(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner owner, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> onChanged);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..b1e79f4
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,9 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataKt {
+    method @MainThread public static inline <T> androidx.lifecycle.Observer<T> observe(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner owner, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> onChanged);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core-ktx/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core-ktx/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core-ktx/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-livedata-core-ktx/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core-ktx/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..b1e79f4
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core-ktx/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,9 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataKt {
+    method @MainThread public static inline <T> androidx.lifecycle.Observer<T> observe(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner owner, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> onChanged);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..f0db7db
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core/api/2.3.0-alpha04.txt
@@ -0,0 +1,32 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LiveData<T> {
+    ctor public LiveData(T!);
+    ctor public LiveData();
+    method public T? getValue();
+    method public boolean hasActiveObservers();
+    method public boolean hasObservers();
+    method @MainThread public void observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void observeForever(androidx.lifecycle.Observer<? super T>);
+    method protected void onActive();
+    method protected void onInactive();
+    method protected void postValue(T!);
+    method @MainThread public void removeObserver(androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void removeObservers(androidx.lifecycle.LifecycleOwner);
+    method @MainThread protected void setValue(T!);
+  }
+
+  public class MutableLiveData<T> extends androidx.lifecycle.LiveData<T> {
+    ctor public MutableLiveData(T!);
+    ctor public MutableLiveData();
+    method public void postValue(T!);
+    method public void setValue(T!);
+  }
+
+  public interface Observer<T> {
+    method public void onChanged(T!);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..f0db7db
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,32 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LiveData<T> {
+    ctor public LiveData(T!);
+    ctor public LiveData();
+    method public T? getValue();
+    method public boolean hasActiveObservers();
+    method public boolean hasObservers();
+    method @MainThread public void observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void observeForever(androidx.lifecycle.Observer<? super T>);
+    method protected void onActive();
+    method protected void onInactive();
+    method protected void postValue(T!);
+    method @MainThread public void removeObserver(androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void removeObservers(androidx.lifecycle.LifecycleOwner);
+    method @MainThread protected void setValue(T!);
+  }
+
+  public class MutableLiveData<T> extends androidx.lifecycle.LiveData<T> {
+    ctor public MutableLiveData(T!);
+    ctor public MutableLiveData();
+    method public void postValue(T!);
+    method public void setValue(T!);
+  }
+
+  public interface Observer<T> {
+    method public void onChanged(T!);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-livedata-core/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-core/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..f0db7db
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-core/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,32 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LiveData<T> {
+    ctor public LiveData(T!);
+    ctor public LiveData();
+    method public T? getValue();
+    method public boolean hasActiveObservers();
+    method public boolean hasObservers();
+    method @MainThread public void observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void observeForever(androidx.lifecycle.Observer<? super T>);
+    method protected void onActive();
+    method protected void onInactive();
+    method protected void postValue(T!);
+    method @MainThread public void removeObserver(androidx.lifecycle.Observer<? super T>);
+    method @MainThread public void removeObservers(androidx.lifecycle.LifecycleOwner);
+    method @MainThread protected void setValue(T!);
+  }
+
+  public class MutableLiveData<T> extends androidx.lifecycle.LiveData<T> {
+    ctor public MutableLiveData(T!);
+    ctor public MutableLiveData();
+    method public void postValue(T!);
+    method public void setValue(T!);
+  }
+
+  public interface Observer<T> {
+    method public void onChanged(T!);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-core/src/main/java/androidx/lifecycle/LiveData.java b/lifecycle/lifecycle-livedata-core/src/main/java/androidx/lifecycle/LiveData.java
index 1e72908..a694fcd 100644
--- a/lifecycle/lifecycle-livedata-core/src/main/java/androidx/lifecycle/LiveData.java
+++ b/lifecycle/lifecycle-livedata-core/src/main/java/androidx/lifecycle/LiveData.java
@@ -69,6 +69,8 @@
     // how many observers are in active state
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     int mActiveCount = 0;
+    // to handle active/inactive reentry, we guard with this boolean
+    private boolean mChangingActiveState;
     private volatile Object mData;
     // when setData is called, we set the pending data and actual data swap happens on the main
     // thread
@@ -371,6 +373,30 @@
         return mActiveCount > 0;
     }
 
+    @MainThread
+    void changeActiveCounter(int change) {
+        int previousActiveCount = mActiveCount;
+        mActiveCount += change;
+        if (mChangingActiveState) {
+            return;
+        }
+        mChangingActiveState = true;
+        try {
+            while (previousActiveCount != mActiveCount) {
+                boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
+                boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
+                previousActiveCount = mActiveCount;
+                if (needToCallActive) {
+                    onActive();
+                } else if (needToCallInactive) {
+                    onInactive();
+                }
+            }
+        } finally {
+            mChangingActiveState = false;
+        }
+    }
+
     class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
         @NonNull
         final LifecycleOwner mOwner;
@@ -388,11 +414,17 @@
         @Override
         public void onStateChanged(@NonNull LifecycleOwner source,
                 @NonNull Lifecycle.Event event) {
-            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
+            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
+            if (currentState == DESTROYED) {
                 removeObserver(mObserver);
                 return;
             }
-            activeStateChanged(shouldBeActive());
+            Lifecycle.State prevState = null;
+            while (prevState != currentState) {
+                prevState = currentState;
+                activeStateChanged(shouldBeActive());
+                currentState = mOwner.getLifecycle().getCurrentState();
+            }
         }
 
         @Override
@@ -431,14 +463,7 @@
             // immediately set active state, so we'd never dispatch anything to inactive
             // owner
             mActive = newActive;
-            boolean wasInactive = LiveData.this.mActiveCount == 0;
-            LiveData.this.mActiveCount += mActive ? 1 : -1;
-            if (wasInactive && mActive) {
-                onActive();
-            }
-            if (LiveData.this.mActiveCount == 0 && !mActive) {
-                onInactive();
-            }
+            changeActiveCounter(mActive ? 1 : -1);
             if (mActive) {
                 dispatchingValue(this);
             }
diff --git a/lifecycle/lifecycle-livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java b/lifecycle/lifecycle-livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
index a3ecdfd..9932578 100644
--- a/lifecycle/lifecycle-livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
+++ b/lifecycle/lifecycle-livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
@@ -42,6 +42,7 @@
 import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
 import androidx.lifecycle.testing.TestLifecycleOwner;
 
+import org.hamcrest.CoreMatchers;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -52,6 +53,10 @@
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import kotlinx.coroutines.test.TestCoroutineDispatcher;
 
 @SuppressWarnings({"unchecked"})
@@ -810,6 +815,91 @@
         verify(observer).onChanged("foo");
     }
 
+    @Test
+    public void activeReentry_removeOnActive() {
+        mOwner.handleLifecycleEvent(ON_START);
+        final Observer<String> observer = new Observer<String>() {
+            @Override
+            public void onChanged(String s) {
+
+            }
+        };
+        final List<Boolean> activeCalls = new ArrayList<>();
+        LiveData<String> liveData = new MutableLiveData<String>("foo") {
+            @Override
+            protected void onActive() {
+                activeCalls.add(true);
+                super.onActive();
+                removeObserver(observer);
+            }
+
+            @Override
+            protected void onInactive() {
+                activeCalls.add(false);
+                super.onInactive();
+            }
+        };
+
+        liveData.observe(mOwner, observer);
+        assertThat(activeCalls, CoreMatchers.equalTo(Arrays.asList(true, false)));
+    }
+
+    @Test
+    public void activeReentry_addOnInactive() {
+        mOwner.handleLifecycleEvent(ON_START);
+        final Observer<String> observer1 = mock(Observer.class);
+        final Observer<String> observer2 = mock(Observer.class);
+        final List<Boolean> activeCalls = new ArrayList<>();
+        LiveData<String> liveData = new MutableLiveData<String>("foo") {
+            @Override
+            protected void onActive() {
+                activeCalls.add(true);
+                super.onActive();
+            }
+
+            @Override
+            protected void onInactive() {
+                activeCalls.add(false);
+                observe(mOwner, observer2);
+                super.onInactive();
+            }
+        };
+
+        liveData.observe(mOwner, observer1);
+        liveData.removeObserver(observer1);
+        liveData.removeObserver(observer2);
+        assertThat(activeCalls, CoreMatchers.equalTo(Arrays.asList(true, false, true, false,
+                true)));
+    }
+
+    @Test
+    public void activeReentry_lifecycleChangesActive() {
+        mOwner.handleLifecycleEvent(ON_START);
+        final Observer<String> observer = new Observer<String>() {
+            @Override
+            public void onChanged(String s) {
+                mOwner.handleLifecycleEvent(ON_STOP);
+            }
+        };
+        final List<Boolean> activeCalls = new ArrayList<>();
+        LiveData<String> liveData = new MutableLiveData<String>("foo") {
+            @Override
+            protected void onActive() {
+                activeCalls.add(true);
+                super.onActive();
+            }
+
+            @Override
+            protected void onInactive() {
+                activeCalls.add(false);
+                super.onInactive();
+            }
+        };
+        liveData.observe(mOwner, observer);
+        assertThat(mOwner.getCurrentState(), is(Lifecycle.State.CREATED));
+        assertThat(activeCalls, is(Arrays.asList(true, false)));
+    }
+
     private LifecycleEventObserver getLiveDataInternalObserver(Lifecycle lifecycle) {
         ArgumentCaptor<LifecycleEventObserver> captor =
                 ArgumentCaptor.forClass(LifecycleEventObserver.class);
diff --git a/lifecycle/lifecycle-livedata-ktx/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-ktx/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..409e721
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-ktx/api/2.3.0-alpha04.txt
@@ -0,0 +1,31 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class CoroutineLiveDataKt {
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class FlowLiveDataConversions {
+    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout);
+  }
+
+  public interface LiveDataScope<T> {
+    method public suspend Object? emit(T? value, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle> p);
+    method public T? getLatestValue();
+    property public abstract T? latestValue;
+  }
+
+  public final class TransformationsKt {
+    method public static inline <X> androidx.lifecycle.LiveData<X> distinctUntilChanged(androidx.lifecycle.LiveData<X>);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> map(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends Y> transform);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> switchMap(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends androidx.lifecycle.LiveData<Y>> transform);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..409e721
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,31 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class CoroutineLiveDataKt {
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class FlowLiveDataConversions {
+    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout);
+  }
+
+  public interface LiveDataScope<T> {
+    method public suspend Object? emit(T? value, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle> p);
+    method public T? getLatestValue();
+    property public abstract T? latestValue;
+  }
+
+  public final class TransformationsKt {
+    method public static inline <X> androidx.lifecycle.LiveData<X> distinctUntilChanged(androidx.lifecycle.LiveData<X>);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> map(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends Y> transform);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> switchMap(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends androidx.lifecycle.LiveData<Y>> transform);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-ktx/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-ktx/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-ktx/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-livedata-ktx/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata-ktx/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..409e721
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-ktx/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,31 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class CoroutineLiveDataKt {
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout, @kotlin.BuilderInference kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class FlowLiveDataConversions {
+    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, long timeoutInMs = 5000L);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, kotlin.coroutines.CoroutineContext context = EmptyCoroutineContext, java.time.Duration timeout);
+  }
+
+  public interface LiveDataScope<T> {
+    method public suspend Object? emit(T? value, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle> p);
+    method public T? getLatestValue();
+    property public abstract T? latestValue;
+  }
+
+  public final class TransformationsKt {
+    method public static inline <X> androidx.lifecycle.LiveData<X> distinctUntilChanged(androidx.lifecycle.LiveData<X>);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> map(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends Y> transform);
+    method public static inline <X, Y> androidx.lifecycle.LiveData<Y> switchMap(androidx.lifecycle.LiveData<X>, kotlin.jvm.functions.Function1<? super X,? extends androidx.lifecycle.LiveData<Y>> transform);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata-ktx/build.gradle b/lifecycle/lifecycle-livedata-ktx/build.gradle
index f767d23..de01694 100644
--- a/lifecycle/lifecycle-livedata-ktx/build.gradle
+++ b/lifecycle/lifecycle-livedata-ktx/build.gradle
@@ -45,6 +45,12 @@
     testImplementation(JUNIT)
     testImplementation(TRUTH)
     testImplementation(KOTLIN_COROUTINES_TEST)
+    androidTestImplementation(TRUTH)
+    androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
+    androidTestImplementation(ANDROIDX_TEST_CORE)
+    androidTestImplementation(ANDROIDX_TEST_RUNNER)
+    androidTestImplementation(KOTLIN_COROUTINES_TEST)
+    androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
 }
 
 androidx {
diff --git a/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt b/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
new file mode 100644
index 0000000..eee40a8
--- /dev/null
+++ b/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.lifecycle
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.channelFlow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
+@RunWith(AndroidJUnit4::class)
+class FlowAsLiveDataIntegrationTest {
+    @Test
+    @SmallTest
+    fun startStopImmediately() {
+        runBlocking {
+            val mediator = withContext(Dispatchers.Main) {
+                val mediator = MediatorLiveData<Int>()
+                val liveData = channelFlow {
+                    send(1)
+                    delay(30000) // prevent block from ending
+                }.asLiveData()
+                mediator.addSource(liveData) {
+                    mediator.removeSource(liveData)
+                    mediator.value = -it
+                }
+                mediator
+            }
+            val read = mediator.asFlow().first()
+            Truth.assertThat(read).isEqualTo(-1)
+        }
+    }
+}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-livedata/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..b9a2837
--- /dev/null
+++ b/lifecycle/lifecycle-livedata/api/2.3.0-alpha04.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class MediatorLiveData<T> extends androidx.lifecycle.MutableLiveData<T> {
+    ctor public MediatorLiveData();
+    method @MainThread public <S> void addSource(androidx.lifecycle.LiveData<S!>, androidx.lifecycle.Observer<? super S>);
+    method @MainThread public <S> void removeSource(androidx.lifecycle.LiveData<S!>);
+  }
+
+  public class Transformations {
+    method @MainThread public static <X> androidx.lifecycle.LiveData<X!> distinctUntilChanged(androidx.lifecycle.LiveData<X!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> map(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,Y!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> switchMap(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,androidx.lifecycle.LiveData<Y!>!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..b9a2837
--- /dev/null
+++ b/lifecycle/lifecycle-livedata/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class MediatorLiveData<T> extends androidx.lifecycle.MutableLiveData<T> {
+    ctor public MediatorLiveData();
+    method @MainThread public <S> void addSource(androidx.lifecycle.LiveData<S!>, androidx.lifecycle.Observer<? super S>);
+    method @MainThread public <S> void removeSource(androidx.lifecycle.LiveData<S!>);
+  }
+
+  public class Transformations {
+    method @MainThread public static <X> androidx.lifecycle.LiveData<X!> distinctUntilChanged(androidx.lifecycle.LiveData<X!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> map(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,Y!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> switchMap(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,androidx.lifecycle.LiveData<Y!>!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-livedata/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-livedata/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-livedata/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-livedata/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..5d2ddfa
--- /dev/null
+++ b/lifecycle/lifecycle-livedata/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,25 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class ComputableLiveData<T> {
+    ctor public ComputableLiveData();
+    ctor public ComputableLiveData(java.util.concurrent.Executor);
+    method @WorkerThread protected abstract T! compute();
+    method public androidx.lifecycle.LiveData<T!> getLiveData();
+    method public void invalidate();
+  }
+
+  public class MediatorLiveData<T> extends androidx.lifecycle.MutableLiveData<T> {
+    ctor public MediatorLiveData();
+    method @MainThread public <S> void addSource(androidx.lifecycle.LiveData<S!>, androidx.lifecycle.Observer<? super S>);
+    method @MainThread public <S> void removeSource(androidx.lifecycle.LiveData<S!>);
+  }
+
+  public class Transformations {
+    method @MainThread public static <X> androidx.lifecycle.LiveData<X!> distinctUntilChanged(androidx.lifecycle.LiveData<X!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> map(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,Y!>);
+    method @MainThread public static <X, Y> androidx.lifecycle.LiveData<Y!> switchMap(androidx.lifecycle.LiveData<X!>, androidx.arch.core.util.Function<X!,androidx.lifecycle.LiveData<Y!>!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-process/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-process/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..beea619
--- /dev/null
+++ b/lifecycle/lifecycle-process/api/2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class ProcessLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner get();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-process/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-process/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..beea619
--- /dev/null
+++ b/lifecycle/lifecycle-process/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class ProcessLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner get();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-process/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-process/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-process/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-process/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-process/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..ba282a3
--- /dev/null
+++ b/lifecycle/lifecycle-process/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,20 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class ProcessLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner get();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ProcessLifecycleOwnerInitializer extends android.content.ContentProvider {
+    ctor public ProcessLifecycleOwnerInitializer();
+    method public int delete(android.net.Uri, String!, String![]!);
+    method public String? getType(android.net.Uri);
+    method public android.net.Uri? insert(android.net.Uri, android.content.ContentValues!);
+    method public boolean onCreate();
+    method public android.database.Cursor? query(android.net.Uri, String![]!, String!, String![]!, String!);
+    method public int update(android.net.Uri, android.content.ContentValues!, String!, String![]!);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams-ktx/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams-ktx/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..0f61097
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams-ktx/api/2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveSteamsKt {
+    method public static inline <T> androidx.lifecycle.LiveData<T> toLiveData(org.reactivestreams.Publisher<T>);
+    method public static inline <T> org.reactivestreams.Publisher<T> toPublisher(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner lifecycle);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..0f61097
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveSteamsKt {
+    method public static inline <T> androidx.lifecycle.LiveData<T> toLiveData(org.reactivestreams.Publisher<T>);
+    method public static inline <T> org.reactivestreams.Publisher<T> toPublisher(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner lifecycle);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams-ktx/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams-ktx/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams-ktx/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-reactivestreams-ktx/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams-ktx/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..0f61097
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams-ktx/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveSteamsKt {
+    method public static inline <T> androidx.lifecycle.LiveData<T> toLiveData(org.reactivestreams.Publisher<T>);
+    method public static inline <T> org.reactivestreams.Publisher<T> toPublisher(androidx.lifecycle.LiveData<T>, androidx.lifecycle.LifecycleOwner lifecycle);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..518fc95
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams/api/2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveStreams {
+    method public static <T> androidx.lifecycle.LiveData<T!> fromPublisher(org.reactivestreams.Publisher<T!>);
+    method public static <T> org.reactivestreams.Publisher<T!> toPublisher(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.LiveData<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..518fc95
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveStreams {
+    method public static <T> androidx.lifecycle.LiveData<T!> fromPublisher(org.reactivestreams.Publisher<T!>);
+    method public static <T> org.reactivestreams.Publisher<T!> toPublisher(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.LiveData<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-reactivestreams/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-reactivestreams/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-reactivestreams/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..518fc95
--- /dev/null
+++ b/lifecycle/lifecycle-reactivestreams/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,10 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class LiveDataReactiveStreams {
+    method public static <T> androidx.lifecycle.LiveData<T!> fromPublisher(org.reactivestreams.Publisher<T!>);
+    method public static <T> org.reactivestreams.Publisher<T!> toPublisher(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.LiveData<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..60b6383
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha04.txt
@@ -0,0 +1,33 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LifecycleCoroutineScope implements kotlinx.coroutines.CoroutineScope {
+    method public final kotlinx.coroutines.Job launchWhenCreated(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenResumed(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class LifecycleKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
+  }
+
+  public final class LifecycleOwnerKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getLifecycleScope(androidx.lifecycle.LifecycleOwner);
+  }
+
+  public final class PausingDispatcherKt {
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State minState, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+  public final class ViewKt {
+    method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..60b6383
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,33 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LifecycleCoroutineScope implements kotlinx.coroutines.CoroutineScope {
+    method public final kotlinx.coroutines.Job launchWhenCreated(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenResumed(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class LifecycleKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
+  }
+
+  public final class LifecycleOwnerKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getLifecycleScope(androidx.lifecycle.LifecycleOwner);
+  }
+
+  public final class PausingDispatcherKt {
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State minState, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+  public final class ViewKt {
+    method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-ktx/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-ktx/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..60b6383
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,33 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class LifecycleCoroutineScope implements kotlinx.coroutines.CoroutineScope {
+    method public final kotlinx.coroutines.Job launchWhenCreated(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenResumed(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class LifecycleKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
+  }
+
+  public final class LifecycleOwnerKt {
+    method public static androidx.lifecycle.LifecycleCoroutineScope getLifecycleScope(androidx.lifecycle.LifecycleOwner);
+  }
+
+  public final class PausingDispatcherKt {
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? whenStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State minState, kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+  public final class ViewKt {
+    method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-testing/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-testing/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..edbcffd
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-testing/api/2.3.0-alpha04.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.lifecycle.testing {
+
+  public final class TestLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState);
+    ctor public TestLifecycleOwner();
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public androidx.lifecycle.LifecycleRegistry getLifecycle();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State value);
+    property public final androidx.lifecycle.Lifecycle.State currentState;
+    property public final int observerCount;
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-testing/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-testing/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..edbcffd
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-testing/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.lifecycle.testing {
+
+  public final class TestLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState);
+    ctor public TestLifecycleOwner();
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public androidx.lifecycle.LifecycleRegistry getLifecycle();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State value);
+    property public final androidx.lifecycle.Lifecycle.State currentState;
+    property public final int observerCount;
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime-testing/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-testing/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-testing/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-runtime-testing/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime-testing/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..edbcffd
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-testing/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.lifecycle.testing {
+
+  public final class TestLifecycleOwner implements androidx.lifecycle.LifecycleOwner {
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+    ctor public TestLifecycleOwner(androidx.lifecycle.Lifecycle.State initialState);
+    ctor public TestLifecycleOwner();
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public androidx.lifecycle.LifecycleRegistry getLifecycle();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
+    method public void setCurrentState(androidx.lifecycle.Lifecycle.State value);
+    property public final androidx.lifecycle.Lifecycle.State currentState;
+    property public final int observerCount;
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..af2571b
--- /dev/null
+++ b/lifecycle/lifecycle-runtime/api/2.3.0-alpha04.txt
@@ -0,0 +1,25 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver);
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+  }
+
+  @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
+    method @Deprecated public androidx.lifecycle.LifecycleRegistry getLifecycle();
+  }
+
+  public class ViewTreeLifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.LifecycleOwner?);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..af2571b
--- /dev/null
+++ b/lifecycle/lifecycle-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,25 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver);
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+  }
+
+  @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
+    method @Deprecated public androidx.lifecycle.LifecycleRegistry getLifecycle();
+  }
+
+  public class ViewTreeLifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.LifecycleOwner?);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-runtime/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-runtime/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-runtime/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-runtime/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..36010e4
--- /dev/null
+++ b/lifecycle/lifecycle-runtime/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleRegistry extends androidx.lifecycle.Lifecycle {
+    ctor public LifecycleRegistry(androidx.lifecycle.LifecycleOwner);
+    method public void addObserver(androidx.lifecycle.LifecycleObserver);
+    method public androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public int getObserverCount();
+    method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event);
+    method @Deprecated @MainThread public void markState(androidx.lifecycle.Lifecycle.State);
+    method public void removeObserver(androidx.lifecycle.LifecycleObserver);
+    method @MainThread public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+  }
+
+  @Deprecated public interface LifecycleRegistryOwner extends androidx.lifecycle.LifecycleOwner {
+    method @Deprecated public androidx.lifecycle.LifecycleRegistry getLifecycle();
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ReportFragment extends android.app.Fragment {
+    ctor public ReportFragment();
+    method public static void injectIfNeededIn(android.app.Activity!);
+    method public void onActivityCreated(android.os.Bundle!);
+    method public void onDestroy();
+    method public void onPause();
+    method public void onResume();
+    method public void onStart();
+    method public void onStop();
+  }
+
+  public class ViewTreeLifecycleOwner {
+    method public static androidx.lifecycle.LifecycleOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.LifecycleOwner?);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-service/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-service/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..e3c2893
--- /dev/null
+++ b/lifecycle/lifecycle-service/api/2.3.0-alpha04.txt
@@ -0,0 +1,21 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleService extends android.app.Service implements androidx.lifecycle.LifecycleOwner {
+    ctor public LifecycleService();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+    method @CallSuper public void onStart(android.content.Intent?, int);
+  }
+
+  public class ServiceLifecycleDispatcher {
+    ctor public ServiceLifecycleDispatcher(androidx.lifecycle.LifecycleOwner);
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public void onServicePreSuperOnBind();
+    method public void onServicePreSuperOnCreate();
+    method public void onServicePreSuperOnDestroy();
+    method public void onServicePreSuperOnStart();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-service/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-service/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..e3c2893
--- /dev/null
+++ b/lifecycle/lifecycle-service/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,21 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleService extends android.app.Service implements androidx.lifecycle.LifecycleOwner {
+    ctor public LifecycleService();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+    method @CallSuper public void onStart(android.content.Intent?, int);
+  }
+
+  public class ServiceLifecycleDispatcher {
+    ctor public ServiceLifecycleDispatcher(androidx.lifecycle.LifecycleOwner);
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public void onServicePreSuperOnBind();
+    method public void onServicePreSuperOnCreate();
+    method public void onServicePreSuperOnDestroy();
+    method public void onServicePreSuperOnStart();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-service/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-service/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-service/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-service/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-service/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..e3c2893
--- /dev/null
+++ b/lifecycle/lifecycle-service/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,21 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class LifecycleService extends android.app.Service implements androidx.lifecycle.LifecycleOwner {
+    ctor public LifecycleService();
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+    method @CallSuper public void onStart(android.content.Intent?, int);
+  }
+
+  public class ServiceLifecycleDispatcher {
+    ctor public ServiceLifecycleDispatcher(androidx.lifecycle.LifecycleOwner);
+    method public androidx.lifecycle.Lifecycle getLifecycle();
+    method public void onServicePreSuperOnBind();
+    method public void onServicePreSuperOnCreate();
+    method public void onServicePreSuperOnDestroy();
+    method public void onServicePreSuperOnStart();
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-ktx/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-ktx/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..4fb6e5a
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-ktx/api/2.3.0-alpha04.txt
@@ -0,0 +1,24 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class ViewModelKt {
+    method public static kotlinx.coroutines.CoroutineScope getViewModelScope(androidx.lifecycle.ViewModel);
+  }
+
+  public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+    ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
+    method public VM getValue();
+    method public boolean isInitialized();
+    property public VM value;
+  }
+
+  public final class ViewModelProviderKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! get(androidx.lifecycle.ViewModelProvider);
+  }
+
+  public final class ViewTreeViewModelKt {
+    method public static androidx.lifecycle.ViewModelStoreOwner? findViewTreeViewModelStoreOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..4fb6e5a
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,24 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class ViewModelKt {
+    method public static kotlinx.coroutines.CoroutineScope getViewModelScope(androidx.lifecycle.ViewModel);
+  }
+
+  public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+    ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
+    method public VM getValue();
+    method public boolean isInitialized();
+    property public VM value;
+  }
+
+  public final class ViewModelProviderKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! get(androidx.lifecycle.ViewModelProvider);
+  }
+
+  public final class ViewTreeViewModelKt {
+    method public static androidx.lifecycle.ViewModelStoreOwner? findViewTreeViewModelStoreOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-ktx/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-ktx/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-ktx/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-viewmodel-ktx/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-ktx/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..4fb6e5a
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-ktx/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,24 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public final class ViewModelKt {
+    method public static kotlinx.coroutines.CoroutineScope getViewModelScope(androidx.lifecycle.ViewModel);
+  }
+
+  public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+    ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
+    method public VM getValue();
+    method public boolean isInitialized();
+    property public VM value;
+  }
+
+  public final class ViewModelProviderKt {
+    method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! get(androidx.lifecycle.ViewModelProvider);
+  }
+
+  public final class ViewTreeViewModelKt {
+    method public static androidx.lifecycle.ViewModelStoreOwner? findViewTreeViewModelStoreOwner(android.view.View);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..d1638a6
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/2.3.0-alpha04.txt
@@ -0,0 +1,32 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class AbstractSavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public AbstractSavedStateViewModelFactory(androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method public final <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+    method protected abstract <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>, androidx.lifecycle.SavedStateHandle);
+  }
+
+  public final class SavedStateHandle {
+    ctor public SavedStateHandle(java.util.Map<java.lang.String!,java.lang.Object!>);
+    ctor public SavedStateHandle();
+    method @MainThread public void clearSavedStateProvider(String);
+    method @MainThread public boolean contains(String);
+    method @MainThread public <T> T? get(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String, T!);
+    method @MainThread public java.util.Set<java.lang.String!> keys();
+    method @MainThread public <T> T? remove(String);
+    method @MainThread public <T> void set(String, T?);
+    method @MainThread public void setSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
+  }
+
+  public final class SavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner);
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method public <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..d1638a6
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,32 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class AbstractSavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public AbstractSavedStateViewModelFactory(androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method public final <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+    method protected abstract <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>, androidx.lifecycle.SavedStateHandle);
+  }
+
+  public final class SavedStateHandle {
+    ctor public SavedStateHandle(java.util.Map<java.lang.String!,java.lang.Object!>);
+    ctor public SavedStateHandle();
+    method @MainThread public void clearSavedStateProvider(String);
+    method @MainThread public boolean contains(String);
+    method @MainThread public <T> T? get(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String, T!);
+    method @MainThread public java.util.Set<java.lang.String!> keys();
+    method @MainThread public <T> T? remove(String);
+    method @MainThread public <T> void set(String, T?);
+    method @MainThread public void setSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
+  }
+
+  public final class SavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner);
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method public <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..ec77411
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,33 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public abstract class AbstractSavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public AbstractSavedStateViewModelFactory(androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
+    method public final <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+    method protected abstract <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>, androidx.lifecycle.SavedStateHandle);
+  }
+
+  public final class SavedStateHandle {
+    ctor public SavedStateHandle(java.util.Map<java.lang.String!,java.lang.Object!>);
+    ctor public SavedStateHandle();
+    method @MainThread public void clearSavedStateProvider(String);
+    method @MainThread public boolean contains(String);
+    method @MainThread public <T> T? get(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String);
+    method @MainThread public <T> androidx.lifecycle.MutableLiveData<T!> getLiveData(String, T!);
+    method @MainThread public java.util.Set<java.lang.String!> keys();
+    method @MainThread public <T> T? remove(String);
+    method @MainThread public <T> void set(String, T?);
+    method @MainThread public void setSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
+  }
+
+  public final class SavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner);
+    ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
+    method public <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/SavedStateFactoryTest.kt b/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/SavedStateFactoryTest.kt
index 978cd5b..52d629b 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/SavedStateFactoryTest.kt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/SavedStateFactoryTest.kt
@@ -27,7 +27,6 @@
 import androidx.lifecycle.ViewModelStore
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.fail
 import org.junit.Rule
@@ -38,8 +37,9 @@
 @SmallTest
 class SavedStateFactoryTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(MyActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(MyActivity::class.java)
 
     @Test
     fun testCreateAndroidVM() {
diff --git a/lifecycle/lifecycle-viewmodel/api/2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel/api/2.3.0-alpha04.txt
new file mode 100644
index 0000000..7df8caf
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel/api/2.3.0-alpha04.txt
@@ -0,0 +1,55 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class AndroidViewModel extends androidx.lifecycle.ViewModel {
+    ctor public AndroidViewModel(android.app.Application);
+    method public <T extends android.app.Application> T getApplication();
+  }
+
+  public interface HasDefaultViewModelProviderFactory {
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+  }
+
+  public abstract class ViewModel {
+    ctor public ViewModel();
+    method protected void onCleared();
+  }
+
+  public class ViewModelProvider {
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner, androidx.lifecycle.ViewModelProvider.Factory);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore, androidx.lifecycle.ViewModelProvider.Factory);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(Class<T!>);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
+  }
+
+  public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
+    ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
+    method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
+  }
+
+  public static interface ViewModelProvider.Factory {
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public ViewModelProvider.NewInstanceFactory();
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public class ViewModelStore {
+    ctor public ViewModelStore();
+    method public final void clear();
+  }
+
+  public interface ViewModelStoreOwner {
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+  }
+
+  public class ViewTreeViewModelStoreOwner {
+    method public static androidx.lifecycle.ViewModelStoreOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.ViewModelStoreOwner?);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_2.3.0-alpha04.txt
new file mode 100644
index 0000000..7df8caf
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -0,0 +1,55 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class AndroidViewModel extends androidx.lifecycle.ViewModel {
+    ctor public AndroidViewModel(android.app.Application);
+    method public <T extends android.app.Application> T getApplication();
+  }
+
+  public interface HasDefaultViewModelProviderFactory {
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+  }
+
+  public abstract class ViewModel {
+    ctor public ViewModel();
+    method protected void onCleared();
+  }
+
+  public class ViewModelProvider {
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner, androidx.lifecycle.ViewModelProvider.Factory);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore, androidx.lifecycle.ViewModelProvider.Factory);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(Class<T!>);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
+  }
+
+  public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
+    ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
+    method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
+  }
+
+  public static interface ViewModelProvider.Factory {
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public ViewModelProvider.NewInstanceFactory();
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public class ViewModelStore {
+    ctor public ViewModelStore();
+    method public final void clear();
+  }
+
+  public interface ViewModelStoreOwner {
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+  }
+
+  public class ViewTreeViewModelStoreOwner {
+    method public static androidx.lifecycle.ViewModelStoreOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.ViewModelStoreOwner?);
+  }
+
+}
+
diff --git a/lifecycle/lifecycle-viewmodel/api/res-2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel/api/res-2.3.0-alpha04.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel/api/res-2.3.0-alpha04.txt
diff --git a/lifecycle/lifecycle-viewmodel/api/restricted_2.3.0-alpha04.txt b/lifecycle/lifecycle-viewmodel/api/restricted_2.3.0-alpha04.txt
new file mode 100644
index 0000000..7df8caf
--- /dev/null
+++ b/lifecycle/lifecycle-viewmodel/api/restricted_2.3.0-alpha04.txt
@@ -0,0 +1,55 @@
+// Signature format: 3.0
+package androidx.lifecycle {
+
+  public class AndroidViewModel extends androidx.lifecycle.ViewModel {
+    ctor public AndroidViewModel(android.app.Application);
+    method public <T extends android.app.Application> T getApplication();
+  }
+
+  public interface HasDefaultViewModelProviderFactory {
+    method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+  }
+
+  public abstract class ViewModel {
+    ctor public ViewModel();
+    method protected void onCleared();
+  }
+
+  public class ViewModelProvider {
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner, androidx.lifecycle.ViewModelProvider.Factory);
+    ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore, androidx.lifecycle.ViewModelProvider.Factory);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(Class<T!>);
+    method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
+  }
+
+  public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
+    ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
+    method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
+  }
+
+  public static interface ViewModelProvider.Factory {
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
+    ctor public ViewModelProvider.NewInstanceFactory();
+    method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
+  }
+
+  public class ViewModelStore {
+    ctor public ViewModelStore();
+    method public final void clear();
+  }
+
+  public interface ViewModelStoreOwner {
+    method public androidx.lifecycle.ViewModelStore getViewModelStore();
+  }
+
+  public class ViewTreeViewModelStoreOwner {
+    method public static androidx.lifecycle.ViewModelStoreOwner? get(android.view.View);
+    method public static void set(android.view.View, androidx.lifecycle.ViewModelStoreOwner?);
+  }
+
+}
+
diff --git a/localbroadcastmanager/localbroadcastmanager/api/res-1.0.0.txt b/localbroadcastmanager/localbroadcastmanager/api/res-1.0.0.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/localbroadcastmanager/localbroadcastmanager/api/res-1.0.0.txt
diff --git a/media/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java b/media/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
index 10d92562..982bcf6 100644
--- a/media/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/media/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -571,11 +571,14 @@
             setCallback(new Callback() {}, handler);
             mImpl.setMediaButtonReceiver(mbrIntent);
         } else if (android.os.Build.VERSION.SDK_INT >= 19) {
-            mImpl = new MediaSessionImplApi19(context, tag, mbrComponent, mbrIntent, sessionInfo);
+            mImpl = new MediaSessionImplApi19(context, tag, mbrComponent, mbrIntent,
+                    session2Token, sessionInfo);
         } else if (android.os.Build.VERSION.SDK_INT >= 18) {
-            mImpl = new MediaSessionImplApi18(context, tag, mbrComponent, mbrIntent, sessionInfo);
+            mImpl = new MediaSessionImplApi18(context, tag, mbrComponent, mbrIntent,
+                    session2Token, sessionInfo);
         } else {
-            mImpl = new MediaSessionImplBase(context, tag, mbrComponent, mbrIntent, sessionInfo);
+            mImpl = new MediaSessionImplBase(context, tag, mbrComponent, mbrIntent, session2Token,
+                    sessionInfo);
         }
         mController = new MediaControllerCompat(context, this);
 
@@ -2408,7 +2411,7 @@
         };
 
         public MediaSessionImplBase(Context context, String tag, ComponentName mbrComponent,
-                PendingIntent mbrIntent, Bundle sessionInfo) {
+                PendingIntent mbrIntent, VersionedParcelable session2Token, Bundle sessionInfo) {
             if (mbrComponent == null) {
                 throw new IllegalArgumentException(
                         "MediaButtonReceiver component may not be null");
@@ -2421,7 +2424,7 @@
             mMediaButtonReceiverComponentName = mbrComponent;
             mMediaButtonReceiverIntent = mbrIntent;
             mStub = new MediaSessionStub();
-            mToken = new Token(mStub);
+            mToken = new Token(mStub, /* extraBinder= */ null, session2Token);
 
             mRatingType = RatingCompat.RATING_NONE;
             mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
@@ -3599,8 +3602,8 @@
         private static boolean sIsMbrPendingIntentSupported = true;
 
         MediaSessionImplApi18(Context context, String tag, ComponentName mbrComponent,
-                PendingIntent mbrIntent, Bundle sessionInfo) {
-            super(context, tag, mbrComponent, mbrIntent, sessionInfo);
+                PendingIntent mbrIntent, VersionedParcelable session2Token, Bundle sessionInfo) {
+            super(context, tag, mbrComponent, mbrIntent, session2Token, sessionInfo);
         }
 
         @Override
@@ -3683,8 +3686,8 @@
     @RequiresApi(19)
     static class MediaSessionImplApi19 extends MediaSessionImplApi18 {
         MediaSessionImplApi19(Context context, String tag, ComponentName mbrComponent,
-                PendingIntent mbrIntent, Bundle sessionInfo) {
-            super(context, tag, mbrComponent, mbrIntent, sessionInfo);
+                PendingIntent mbrIntent, VersionedParcelable session2Token, Bundle sessionInfo) {
+            super(context, tag, mbrComponent, mbrIntent, session2Token, sessionInfo);
         }
 
         @Override
diff --git a/media2/session/src/main/java/androidx/media2/session/MediaController.java b/media2/session/src/main/java/androidx/media2/session/MediaController.java
index 4ac800d..1232481 100644
--- a/media2/session/src/main/java/androidx/media2/session/MediaController.java
+++ b/media2/session/src/main/java/androidx/media2/session/MediaController.java
@@ -1560,6 +1560,12 @@
 
         @Override
         @NonNull
+        public Builder setConnectionHints(@NonNull Bundle connectionHints) {
+            return super.setConnectionHints(connectionHints);
+        }
+
+        @Override
+        @NonNull
         public Builder setControllerCallback(@NonNull Executor executor,
                 @NonNull ControllerCallback callback) {
             return super.setControllerCallback(executor, callback);
@@ -1667,7 +1673,7 @@
          */
         @NonNull
         @SuppressWarnings("unchecked")
-        public U setSessionToken(@NonNull SessionToken token) {
+        U setSessionToken(@NonNull SessionToken token) {
             if (token == null) {
                 throw new NullPointerException("token shouldn't be null");
             }
@@ -1687,7 +1693,7 @@
          */
         @NonNull
         @SuppressWarnings("unchecked")
-        public U setSessionCompatToken(@NonNull MediaSessionCompat.Token compatToken) {
+        U setSessionCompatToken(@NonNull MediaSessionCompat.Token compatToken) {
             if (compatToken == null) {
                 throw new NullPointerException("compatToken shouldn't be null");
             }
@@ -1733,7 +1739,7 @@
          */
         @NonNull
         @SuppressWarnings("unchecked")
-        public U setControllerCallback(@NonNull Executor executor, @NonNull C callback) {
+        U setControllerCallback(@NonNull Executor executor, @NonNull C callback) {
             if (executor == null) {
                 throw new NullPointerException("executor shouldn't be null");
             }
diff --git a/media2/session/src/main/java/androidx/media2/session/MediaSession.java b/media2/session/src/main/java/androidx/media2/session/MediaSession.java
index a5f6b05..f6447861 100644
--- a/media2/session/src/main/java/androidx/media2/session/MediaSession.java
+++ b/media2/session/src/main/java/androidx/media2/session/MediaSession.java
@@ -1375,7 +1375,7 @@
          */
         @NonNull
         @SuppressWarnings("unchecked")
-        public U setExtras(@NonNull Bundle extras) {
+        U setExtras(@NonNull Bundle extras) {
             if (extras == null) {
                 throw new NullPointerException("extras shouldn't be null");
             }
diff --git a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
index 06953cf..1246dfb 100644
--- a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -32,8 +31,9 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class DynamicFragmentNavigatorDestinationBuilderTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragmentTest.kt b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragmentTest.kt
index 5f2f25f..e12afd8 100644
--- a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragmentTest.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragmentTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.withActivity
 import org.junit.Assert.assertNotEquals
 import org.junit.Rule
@@ -33,8 +32,9 @@
 @RunWith(AndroidJUnit4::class)
 class DynamicNavHostFragmentTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(NavigationActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule(NavigationActivity::class.java)
 
     @Test
     fun createSplitInstallManager() {
diff --git a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
index a3885b6..f252355 100644
--- a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
@@ -22,7 +22,6 @@
 import androidx.navigation.NoOpNavigator
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.android.play.core.splitinstall.SplitInstallManager
 import org.junit.Assert.assertNotNull
 import org.junit.Before
@@ -43,8 +42,9 @@
     private lateinit var noOpNavigator: NoOpNavigator
     private lateinit var dynamicDestination: DynamicActivityNavigator.Destination
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(NavigationActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule(NavigationActivity::class.java)
 
     @Before
     fun setup() {
diff --git a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
index 28889d5..680c3b0 100644
--- a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
@@ -23,7 +23,6 @@
 import androidx.navigation.dynamicfeatures.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.fail
@@ -39,8 +38,9 @@
 
     private lateinit var navigator: DynamicIncludeGraphNavigator
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule(NavigationActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule(NavigationActivity::class.java)
 
     @Before
     fun setup() {
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
index a609234..121ad32 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -32,8 +31,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class DialogFragmentNavigatorDestinationBuilderTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
index e1ad9dc..b05d626 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
@@ -23,7 +23,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Rule
@@ -33,8 +32,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class TestNavigatorDestinationBuilderTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
 
     @UiThreadTest
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
index 9e55a1f..4c7e1d7 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
@@ -23,7 +23,6 @@
 import androidx.navigation.fragment.ktx.test.R
 import androidx.test.annotation.UiThreadTest
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertTrue
 import org.junit.Assert.fail
@@ -32,7 +31,9 @@
 
 @LargeTest
 class ActivityTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @get:Rule
+    val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private val fragmentManager get() = activityRule.activity.supportFragmentManager
     private val contentFragment get() = fragmentManager.findFragmentById(android.R.id.content)!!
 
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
index 67093f6..a373dd1 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
@@ -32,7 +32,6 @@
 import androidx.navigation.plusAssign
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.TestNavigator
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -51,8 +50,13 @@
         private const val TEST_DEEP_LINK_ACTION = "deep_link"
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(activityClass, false, false)
+    var activityRule = androidx.test.rule.ActivityTestRule(
+        activityClass,
+        false,
+        false
+    )
 
     private lateinit var instrumentation: Instrumentation
 
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorTest.kt
index 25b3700..4c7b39a 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorTest.kt
@@ -26,7 +26,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Before
@@ -42,8 +41,9 @@
         private const val INITIAL_FRAGMENT = 1
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmptyActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyActivity::class.java)
 
     private lateinit var emptyActivity: EmptyActivity
     private lateinit var fragmentManager: FragmentManager
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
index 19455e5..ab19723 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
@@ -28,7 +28,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -37,8 +36,13 @@
 @RunWith(AndroidJUnit4::class)
 class EmbeddedXmlTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmbeddedXmlActivity::class.java, false, false)
+    var activityRule = androidx.test.rule.ActivityTestRule(
+        EmbeddedXmlActivity::class.java,
+        false,
+        false
+    )
 
     @Test
     @Throws(Throwable::class)
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
index 9e1af99..8a0e324 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
@@ -28,7 +28,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert.assertEquals
@@ -52,8 +51,9 @@
         private const val TEST_LABEL = "test_label"
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(EmptyActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(EmptyActivity::class.java)
 
     private lateinit var emptyActivity: EmptyActivity
     private lateinit var fragmentManager: FragmentManager
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/ImmediateNavigationTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/ImmediateNavigationTest.kt
index 3bd64bb..ed55d47 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/ImmediateNavigationTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/ImmediateNavigationTest.kt
@@ -25,7 +25,6 @@
 import androidx.navigation.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -36,8 +35,11 @@
 @RunWith(AndroidJUnit4::class)
 class ImmediateNavigationTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(ImmediateNavigationActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(
+        ImmediateNavigationActivity::class.java
+    )
 
     @Test
     fun testNavigateInOnResume() {
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
index b6a230d..20410c2 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
@@ -27,7 +27,6 @@
 import androidx.navigation.fragment.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Rule
@@ -41,8 +40,9 @@
 @RunWith(AndroidJUnit4::class)
 class StartDestinationArgsTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    var activityRule = ActivityTestRule(StartDestinationArgsActivity::class.java)
+    var activityRule = androidx.test.rule.ActivityTestRule(StartDestinationArgsActivity::class.java)
 
     @Test
     fun testNavigateInOnResume() {
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
index ff17f51..337e5850 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
@@ -21,7 +21,6 @@
 import android.os.Bundle
 import android.view.View
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertTrue
 import org.junit.Assert.fail
@@ -30,7 +29,10 @@
 
 @LargeTest
 class ActivityTest {
-    @get:Rule val activityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @get:Rule val activityRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private val view get() = activityRule.activity.findViewById<View>(VIEW_ID)
 
     @Test fun findNavController() {
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
index fedf166..7beeb5e 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Assert.assertEquals
@@ -63,8 +62,9 @@
         const val TARGET_LABEL = "test_label"
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(ActivityNavigatorActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(ActivityNavigatorActivity::class.java)
 
     private lateinit var activityNavigator: ActivityNavigator
 
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
index 5789706..a954ce9 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
@@ -22,7 +22,6 @@
 import androidx.navigation.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.TestNavigator
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -35,8 +34,9 @@
 @RunWith(AndroidJUnit4::class)
 class NavControllerActivityTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(NavControllerActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(NavControllerActivity::class.java)
 
     private lateinit var navController: NavController
     private lateinit var navigator: TestNavigator
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index a7bf8bc..5c44e74 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -239,8 +239,8 @@
         } catch (e: IllegalArgumentException) {
             assertThat(e)
                 .hasMessageThat().contains(
-                    "navigation destination that matches request $deepLinkRequest is unknown to " +
-                            "this NavController"
+                    "Navigation destination that matches request $deepLinkRequest cannot be " +
+                            "found in the navigation graph ${navController.graph}"
                 )
         }
     }
@@ -952,6 +952,40 @@
     }
 
     @Test
+    fun testNavigateOptionSingleTopReplaceNullArgs() {
+        val navController = createNavController()
+        navController.setGraph(R.navigation.nav_simple)
+        assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.start_test)
+        val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
+        assertThat(navigator.backStack.size).isEqualTo(1)
+        assertThat(navigator.current.second).isNull()
+
+        val args = Bundle()
+        val testKey = "testKey"
+        val testValue = "testValue"
+        args.putString(testKey, testValue)
+
+        var destinationListenerExecuted = false
+
+        navController.navigate(R.id.start_test, args, navOptions {
+            launchSingleTop = true
+        })
+
+        navController.addOnDestinationChangedListener { _, destination, arguments ->
+            destinationListenerExecuted = true
+            assertThat(destination.id).isEqualTo(R.id.start_test)
+            assertThat(arguments?.getString(testKey)).isEqualTo(testValue)
+        }
+
+        assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.start_test)
+        assertThat(navigator.backStack.size).isEqualTo(1)
+
+        val returnedArgs = navigator.current.second
+        assertThat(returnedArgs?.getString(testKey)).isEqualTo(testValue)
+        assertThat(destinationListenerExecuted).isTrue()
+    }
+
+    @Test
     fun testNavigateOptionSingleTopNewArgsIgnore() {
         val navController = createNavController()
         navController.setGraph(R.navigation.nav_simple)
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml
index 9981cc9..e276c1c 100644
--- a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml
+++ b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml
@@ -21,7 +21,6 @@
             app:startDestination="@+id/start_test">
 
     <test android:id="@+id/start_test">
-        <argument android:name="arg1" app:argType="string" />
         <action android:id="@+id/second" app:destination="@+id/second_test" />
     </test>
 
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
index 96b6ba1..e812316 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
@@ -52,7 +52,7 @@
         SavedStateRegistryOwner {
     private final Context mContext;
     private final NavDestination mDestination;
-    private final Bundle mArgs;
+    private Bundle mArgs;
     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
     private final SavedStateRegistryController mSavedStateRegistryController =
             SavedStateRegistryController.create(this);
@@ -109,6 +109,10 @@
         return mArgs;
     }
 
+    void replaceArguments(@Nullable Bundle newArgs) {
+        mArgs = newArgs;
+    }
+
     /**
      * {@inheritDoc}
      * <p>
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
index ed4eb14..91347b0 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
@@ -605,8 +605,12 @@
                 NavBackStackEntryState state = (NavBackStackEntryState) parcelable;
                 NavDestination node = findDestination(state.getDestinationId());
                 if (node == null) {
-                    throw new IllegalStateException("unknown destination during restore: "
-                            + mContext.getResources().getResourceName(state.getDestinationId()));
+                    final String dest = NavDestination.getDisplayName(mContext,
+                            state.getDestinationId());
+                    throw new IllegalStateException("Restoring the Navigation back stack failed:"
+                            + " destination " + dest
+                            + " cannot be found from the current destination "
+                            + getCurrentDestination());
                 }
                 Bundle args = state.getArgs();
                 if (args != null) {
@@ -712,8 +716,11 @@
                 int destinationId = deepLink[index++];
                 NavDestination node = findDestination(destinationId);
                 if (node == null) {
-                    throw new IllegalStateException("unknown destination during deep link: "
-                            + NavDestination.getDisplayName(mContext, destinationId));
+                    final String dest = NavDestination.getDisplayName(mContext, destinationId);
+                    throw new IllegalStateException("Deep Linking failed:"
+                            + " destination " + dest
+                            + " cannot be found from the current destination "
+                            + getCurrentDestination());
                 }
                 navigate(node, bundle,
                         new NavOptions.Builder().setEnterAnim(0).setExitAnim(0).build(), null);
@@ -726,8 +733,10 @@
             int destinationId = deepLink[i];
             NavDestination node = i == 0 ? mGraph : graph.findNode(destinationId);
             if (node == null) {
-                throw new IllegalStateException("unknown destination during deep link: "
-                        + NavDestination.getDisplayName(mContext, destinationId));
+                final String dest = NavDestination.getDisplayName(mContext, destinationId);
+                throw new IllegalStateException("Deep Linking failed:"
+                        + " destination " + dest
+                        + " cannot be found in graph " + graph);
             }
             if (i != deepLink.length - 1) {
                 // We're not at the final NavDestination yet, so keep going through the chain
@@ -913,11 +922,15 @@
         NavDestination node = findDestination(destId);
         if (node == null) {
             final String dest = NavDestination.getDisplayName(mContext, destId);
-            throw new IllegalArgumentException("navigation destination " + dest
-                    + (navAction != null
-                    ? " referenced from action " + NavDestination.getDisplayName(mContext, resId)
-                    : "")
-                    + " is unknown to this NavController");
+            if (navAction != null) {
+                throw new IllegalArgumentException("Navigation destination " + dest
+                        + " referenced from action "
+                        + NavDestination.getDisplayName(mContext, resId)
+                        + " cannot be found from the current destination " + currentNode);
+            } else {
+                throw new IllegalArgumentException("Navigation action/destination " + dest
+                        + " cannot be found from the current destination " + currentNode);
+            }
         }
         navigate(node, combinedArgs, navOptions, navigatorExtras);
     }
@@ -1015,8 +1028,8 @@
             NavDestination node = deepLinkMatch.getDestination();
             navigate(node, args, navOptions, navigatorExtras);
         } else {
-            throw new IllegalArgumentException("navigation destination that matches request "
-                    + request + " is unknown to this NavController");
+            throw new IllegalArgumentException("Navigation destination that matches request "
+                    + request + " cannot be found in the navigation graph " + mGraph);
         }
     }
 
@@ -1074,8 +1087,9 @@
             mBackStack.add(newBackStackEntry);
         } else if (navOptions != null && navOptions.shouldLaunchSingleTop()) {
             launchSingleTop = true;
-            if (mBackStack.peekLast() != null && args != null) {
-                mBackStack.peekLast().getArguments().putAll(args);
+            NavBackStackEntry singleTopBackStackEntry = mBackStack.peekLast();
+            if (singleTopBackStackEntry != null) {
+                singleTopBackStackEntry.replaceArguments(args);
             }
         }
         updateOnBackPressedCallbackEnabled();
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.java b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.java
index 106011f..5f1a05b 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.java
@@ -177,8 +177,8 @@
         }
         if (node == null) {
             final String dest = NavDestination.getDisplayName(mContext, mDestId);
-            throw new IllegalArgumentException("navigation destination " + dest
-                    + " is unknown to this NavController");
+            throw new IllegalArgumentException("Navigation destination " + dest
+                    + " cannot be found in the navigation graph " + mGraph);
         }
         mIntent.putExtra(NavController.KEY_DEEP_LINK_IDS, node.buildDeepLinkIds());
     }
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
index aa1870f..98ec45d 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -511,26 +511,41 @@
                 }
             }
             is RemoteMediator.MediatorResult.Success -> {
-                if (loadType != REFRESH) {
-                    stateLock.withLock {
-                        this@PageFetcherSnapshot.state.loadStates.set(
-                            loadType, true, NotLoading.instance(
-                                endOfPaginationReached = mediatorResult.endOfPaginationReached,
-                                fromMediator = true
-                            )
+                stateLock.withLock {
+                    this@PageFetcherSnapshot.state.loadStates.set(
+                        loadType, true, NotLoading.instance(
+                            endOfPaginationReached = mediatorResult.endOfPaginationReached &&
+                                    loadType != REFRESH,
+                            fromMediator = true
                         )
+                    )
 
-                        val page = Page<Key, Value>(listOf(), null, null)
+                    // Remote REFRESH doesn't send state update immediately, and instead lets local
+                    // REFRESH eventually send the update. This prevents the UI from displaying that
+                    // remote refresh has completed just because the write has completed, even
+                    // though the read has not.
+                    //
+                    // Ideally, we would send this signal anyway, and have the UI intentionally
+                    // ignore it, when desired.
+                    if (loadType != REFRESH) {
+                        // Inserting an empty page to update load state to NotLoading.
+                        val emptyPage = Page<Key, Value>(listOf(), null, null)
                         var loadId = when (loadType) {
-                            REFRESH -> 0
+                            REFRESH -> throw IllegalStateException(
+                                "Attempt to insert an extra REFRESH page due to " +
+                                        "RemoteMediator, which is an invalid operation."
+                            )
                             PREPEND -> state.prependLoadId
                             APPEND -> state.appendLoadId
                         }
 
                         // Keep trying to insert with latest loadId until we succeed.
-                        while (!state.insert(loadId, loadType, page)) {
+                        while (!state.insert(loadId, loadType, emptyPage)) {
                             loadId = when (loadType) {
-                                REFRESH -> 0
+                                REFRESH -> throw IllegalStateException(
+                                    "Attempt to insert an extra REFRESH page due to " +
+                                            "RemoteMediator, which is an invalid operation."
+                                )
                                 PREPEND -> state.prependLoadId
                                 APPEND -> state.appendLoadId
                             }
@@ -538,7 +553,7 @@
 
                         // Push an empty insert event to update LoadState.
                         val pageEvent = with(state) {
-                            page.toPageEvent(loadType, config.enablePlaceholders)
+                            emptyPage.toPageEvent(loadType, config.enablePlaceholders)
                         }
 
                         pageEventCh.send(pageEvent)
diff --git a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
index a3ec7be..65c76f5 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
@@ -1718,6 +1718,74 @@
     }
 
     @Test
+    fun remoteMediator_initialRefreshSuccess() = testScope.runBlockingTest {
+        @OptIn(ExperimentalPagingApi::class)
+        val remoteMediator = object : RemoteMediatorMock() {
+            override suspend fun initialize(): InitializeAction {
+                super.initialize()
+                return InitializeAction.LAUNCH_INITIAL_REFRESH
+            }
+
+            override suspend fun load(
+                loadType: LoadType,
+                state: PagingState<Int, Int>
+            ): MediatorResult {
+                super.load(loadType, state)
+                return MediatorResult.Success(endOfPaginationReached = true)
+            }
+        }
+
+        val config = PagingConfig(
+            pageSize = 1,
+            prefetchDistance = 2,
+            enablePlaceholders = true,
+            initialLoadSize = 1,
+            maxSize = 5
+        )
+        val pager = PageFetcherSnapshot(
+            initialKey = 50,
+            pagingSource = pagingSourceFactory(),
+            config = config,
+            retryFlow = retryCh.asFlow(),
+            triggerRemoteRefresh = true,
+            remoteMediatorAccessor = RemoteMediatorAccessor(remoteMediator)
+        )
+
+        collectPagerData(pager) { pageEvents, _ ->
+            advanceUntilIdle()
+
+            assertThat(pageEvents)
+                .isEqualTo(
+                    listOf<PageEvent<Int>>(
+                        LoadStateUpdate(
+                            loadType = REFRESH,
+                            fromMediator = true,
+                            loadState = Loading
+                        ),
+                        LoadStateUpdate(
+                            loadType = REFRESH,
+                            fromMediator = false,
+                            loadState = Loading
+                        ),
+                        Refresh(
+                            pages = listOf(
+                                TransformablePage(
+                                    originalPageOffset = 0,
+                                    data = listOf(50),
+                                    originalPageSize = 1,
+                                    originalIndices = null
+                                )
+                            ),
+                            placeholdersBefore = 50,
+                            placeholdersAfter = 49,
+                            combinedLoadStates = remoteLoadStatesOf()
+                        )
+                    )
+                )
+        }
+    }
+
+    @Test
     fun jump() = testScope.runBlockingTest {
         pauseDispatcher {
             val config = PagingConfig(
diff --git a/paging/runtime/api/3.0.0-alpha01.txt b/paging/runtime/api/3.0.0-alpha01.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/3.0.0-alpha01.txt
+++ b/paging/runtime/api/3.0.0-alpha01.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/api/current.txt b/paging/runtime/api/current.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/current.txt
+++ b/paging/runtime/api/current.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/api/public_plus_experimental_3.0.0-alpha01.txt b/paging/runtime/api/public_plus_experimental_3.0.0-alpha01.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/public_plus_experimental_3.0.0-alpha01.txt
+++ b/paging/runtime/api/public_plus_experimental_3.0.0-alpha01.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/api/public_plus_experimental_current.txt b/paging/runtime/api/public_plus_experimental_current.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/public_plus_experimental_current.txt
+++ b/paging/runtime/api/public_plus_experimental_current.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/api/restricted_3.0.0-alpha01.txt b/paging/runtime/api/restricted_3.0.0-alpha01.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/restricted_3.0.0-alpha01.txt
+++ b/paging/runtime/api/restricted_3.0.0-alpha01.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/api/restricted_current.txt b/paging/runtime/api/restricted_current.txt
index 4a6caa0..68ab22b 100644
--- a/paging/runtime/api/restricted_current.txt
+++ b/paging/runtime/api/restricted_current.txt
@@ -30,6 +30,7 @@
     method public kotlinx.coroutines.flow.Flow<kotlin.Unit> getDataRefreshFlow();
     method public T? getItem(int index);
     method public int getItemCount();
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public void refresh();
     method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -38,18 +39,19 @@
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
     property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
-  public final class LivePagedListBuilder<Key, Value> {
+  @Deprecated public final class LivePagedListBuilder<Key, Value> {
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
-    method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
-    method public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
   }
 
   public final class LivePagedListKt {
@@ -103,6 +105,7 @@
     method protected final T? getItem(int position);
     method public int getItemCount();
     method public final long getItemId(int position);
+    method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
     method public final void refresh();
     method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function0<kotlin.Unit> listener);
     method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
@@ -113,6 +116,7 @@
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
     method public final androidx.recyclerview.widget.MergeAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
     property public final kotlinx.coroutines.flow.Flow<kotlin.Unit> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
   }
 
   public final class PagingLiveData {
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt
index f205c44..42ae07a 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt
@@ -160,6 +160,70 @@
     }
 
     @Test
+    fun performDiff_fastPathLoadStatesFlow() = testScope.runBlockingTest {
+        val loadEvents = mutableListOf<CombinedLoadStates>()
+        val loadEventJob = launch {
+            differ.loadStateFlow.collect { loadEvents.add(it) }
+        }
+
+        val pager = Pager(
+            config = PagingConfig(
+                pageSize = 2,
+                prefetchDistance = 1,
+                enablePlaceholders = true,
+                initialLoadSize = 2
+            ),
+            initialKey = 50
+        ) {
+            TestPagingSource()
+        }
+
+        val job = launch {
+            pager.flow.collect {
+                differ.submitData(it)
+            }
+        }
+
+        advanceUntilIdle()
+
+        // Assert that all load state updates are sent, even when differ enters fast path for
+        // empty previous list.
+        assertEvents(
+            listOf(
+                REFRESH to Loading,
+                REFRESH to NotLoading(endOfPaginationReached = false)
+            ).toCombinedLoadStatesLocal(),
+            loadEvents
+        )
+        loadEvents.clear()
+
+        job.cancel()
+
+        differ.submitData(TestLifecycleOwner().lifecycle, PagingData.empty())
+        advanceUntilIdle()
+
+        // Assert that all load state updates are sent, even when differ enters fast path for
+        // empty next list.
+        assertEvents(
+            expected = listOf(
+                localLoadStatesOf(
+                    refreshLocal = NotLoading(endOfPaginationReached = false),
+                    prependLocal = NotLoading(endOfPaginationReached = true),
+                    appendLocal = NotLoading(endOfPaginationReached = false)
+                ),
+                localLoadStatesOf(
+                    refreshLocal = NotLoading(endOfPaginationReached = false),
+                    prependLocal = NotLoading(endOfPaginationReached = true),
+                    appendLocal = NotLoading(endOfPaginationReached = true)
+                )
+            ),
+            actual = loadEvents
+        )
+
+        loadEventJob.cancel()
+    }
+
+    @Test
     fun lastAccessedIndex() = testScope.runBlockingTest {
         pauseDispatcher {
             var currentPagedSource: TestPagingSource? = null
diff --git a/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt b/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
index 1dcf927..cf3ce31 100644
--- a/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
+++ b/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
@@ -24,9 +24,13 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.asFlow
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import java.util.concurrent.CopyOnWriteArrayList
@@ -256,6 +260,26 @@
         hasRemoteState = false
     )
 
+    @OptIn(ExperimentalCoroutinesApi::class)
+    private val _loadStateCh = ConflatedBroadcastChannel(combinedLoadStates.snapshot())
+
+    /**
+     * A hot [Flow] of [CombinedLoadStates] that emits a snapshot whenever the loading state of the
+     * current [PagingData] changes.
+     *
+     * This flow is conflated, so it buffers the last update to [CombinedLoadStates] and
+     * immediately delivers the current load states on collection.
+     *
+     * @sample androidx.paging.samples.loadStateFlowSample
+     */
+    @OptIn(FlowPreview::class)
+    val loadStateFlow: Flow<CombinedLoadStates> = _loadStateCh.asFlow()
+
+    init {
+        @OptIn(ExperimentalCoroutinesApi::class, ExperimentalPagingApi::class)
+        addLoadStateListener { _loadStateCh.offer(combinedLoadStates.snapshot()) }
+    }
+
     /**
      * Add a [CombinedLoadStates] listener to observe the loading state of the current [PagingData].
      *
@@ -265,6 +289,8 @@
      * @param listener [LoadStates] listener to receive updates.
      *
      * @see removeLoadStateListener
+     *
+     * @sample androidx.paging.samples.addLoadStateListenerSample
      */
     fun addLoadStateListener(listener: (CombinedLoadStates) -> Unit) {
         // Note: Important to add the listener first before sending off events, in case the
diff --git a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
index 5ea00a1..26e7cd5 100644
--- a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
+++ b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
@@ -36,6 +36,7 @@
  *
  * @see toLiveData
  */
+@Deprecated("PagedList is deprecated and has been replaced by PagingData")
 class LivePagedListBuilder<Key : Any, Value : Any> {
     private val pagingSourceFactory: (() -> PagingSource<Key, Value>)?
     private val dataSourceFactory: DataSource.Factory<Key, Value>?
diff --git a/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt b/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
index 62dc546..f3cf7a5 100644
--- a/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
+++ b/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
@@ -24,6 +24,7 @@
 import androidx.recyclerview.widget.RecyclerView
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.flow.Flow
 
 /**
@@ -151,6 +152,16 @@
     override fun getItemCount() = differ.itemCount
 
     /**
+     * A hot [Flow] of [CombinedLoadStates] that emits a snapshot whenever the loading state of the
+     * current [PagingData] changes.
+     *
+     * This flow is conflated, so it buffers the last update to [CombinedLoadStates] and
+     * immediately delivers the current load states on collection.
+     */
+    @OptIn(FlowPreview::class)
+    val loadStateFlow: Flow<CombinedLoadStates> = differ.loadStateFlow
+
+    /**
      * Add a [CombinedLoadStates] listener to observe the loading state of the current [PagingData].
      *
      * As new [PagingData] generations are submitted and displayed, the listener will be notified to
@@ -222,8 +233,8 @@
         footer: LoadStateAdapter<*>
     ): MergeAdapter {
         addLoadStateListener { loadStates ->
-                header.loadState = loadStates.prepend
-                footer.loadState = loadStates.append
+            header.loadState = loadStates.prepend
+            footer.loadState = loadStates.append
         }
         return MergeAdapter(header, this, footer)
     }
diff --git a/paging/rxjava2/api/3.0.0-alpha01.txt b/paging/rxjava2/api/3.0.0-alpha01.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/3.0.0-alpha01.txt
+++ b/paging/rxjava2/api/3.0.0-alpha01.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/api/current.txt b/paging/rxjava2/api/current.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/current.txt
+++ b/paging/rxjava2/api/current.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha01.txt b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha01.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha01.txt
+++ b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha01.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/api/public_plus_experimental_current.txt b/paging/rxjava2/api/public_plus_experimental_current.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/public_plus_experimental_current.txt
+++ b/paging/rxjava2/api/public_plus_experimental_current.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/api/restricted_3.0.0-alpha01.txt b/paging/rxjava2/api/restricted_3.0.0-alpha01.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/restricted_3.0.0-alpha01.txt
+++ b/paging/rxjava2/api/restricted_3.0.0-alpha01.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/api/restricted_current.txt b/paging/rxjava2/api/restricted_current.txt
index 80ea3543..7ab5c6d 100644
--- a/paging/rxjava2/api/restricted_current.txt
+++ b/paging/rxjava2/api/restricted_current.txt
@@ -1,17 +1,17 @@
 // Signature format: 3.0
 package androidx.paging {
 
-  public final class RxPagedListBuilder<Key, Value> {
+  @Deprecated public final class RxPagedListBuilder<Key, Value> {
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
     ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
-    method public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
-    method public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
-    method public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+    method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+    method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
   }
 
   public final class RxPagedListKt {
diff --git a/paging/rxjava2/src/main/java/androidx/paging/RxPagedList.kt b/paging/rxjava2/src/main/java/androidx/paging/RxPagedList.kt
index 51026ca..12b5747 100644
--- a/paging/rxjava2/src/main/java/androidx/paging/RxPagedList.kt
+++ b/paging/rxjava2/src/main/java/androidx/paging/RxPagedList.kt
@@ -21,15 +21,15 @@
 import io.reactivex.Observable
 import io.reactivex.Scheduler
 
+@Suppress("DEPRECATION")
 private fun <Key : Any, Value : Any> createRxPagedListBuilder(
     dataSourceFactory: DataSource.Factory<Key, Value>,
-    @Suppress("DEPRECATION") config: PagedList.Config,
+    config: PagedList.Config,
     initialLoadKey: Key?,
-    @Suppress("DEPRECATION") boundaryCallback: PagedList.BoundaryCallback<Value>?,
+    boundaryCallback: PagedList.BoundaryCallback<Value>?,
     fetchScheduler: Scheduler?,
     notifyScheduler: Scheduler?
 ): RxPagedListBuilder<Key, Value> {
-    @Suppress("DEPRECATION")
     val builder = RxPagedListBuilder(dataSourceFactory, config)
         .setInitialLoadKey(initialLoadKey)
         .setBoundaryCallback(boundaryCallback)
@@ -38,15 +38,15 @@
     return builder
 }
 
+@Suppress("DEPRECATION")
 private fun <Key : Any, Value : Any> createRxPagedListBuilder(
     pagingSourceFactory: () -> PagingSource<Key, Value>,
-    @Suppress("DEPRECATION") config: PagedList.Config,
+    config: PagedList.Config,
     initialLoadKey: Key?,
-    @Suppress("DEPRECATION") boundaryCallback: PagedList.BoundaryCallback<Value>?,
+    boundaryCallback: PagedList.BoundaryCallback<Value>?,
     fetchScheduler: Scheduler?,
     notifyScheduler: Scheduler?
 ): RxPagedListBuilder<Key, Value> {
-    @Suppress("DEPRECATION")
     val builder = RxPagedListBuilder(pagingSourceFactory, config)
         .setInitialLoadKey(initialLoadKey)
         .setBoundaryCallback(boundaryCallback)
diff --git a/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt b/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
index cac6ebd..51f5673 100644
--- a/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
+++ b/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
@@ -50,6 +50,7 @@
  * @param Value Item type being presented.
  *
  */
+@Deprecated("PagedList is deprecated and has been replaced by PagingData")
 class RxPagedListBuilder<Key : Any, Value : Any> {
     private val pagingSourceFactory: (() -> PagingSource<Key, Value>)?
     private val dataSourceFactory: DataSource.Factory<Key, Value>?
diff --git a/paging/samples/src/main/java/androidx/paging/samples/PagingDataAdapterSample.kt b/paging/samples/src/main/java/androidx/paging/samples/PagingDataAdapterSample.kt
index 5ed3fc4..a886f16 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/PagingDataAdapterSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/PagingDataAdapterSample.kt
@@ -34,8 +34,12 @@
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 import io.reactivex.Flowable
 import io.reactivex.disposables.CompositeDisposable
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
 
 data class User(
@@ -121,12 +125,62 @@
     }
 }
 
+open class FakeView {
+    var isVisible: Boolean = false
+}
+
+class FakeSwipeRefreshLayout : FakeView() {
+    var isRefreshing: Boolean = false
+}
+
+private var retryButton = FakeView()
+private var swipeRefreshLayout = FakeSwipeRefreshLayout()
+private var emptyState = FakeView()
+
 @Sampled
+fun addLoadStateListenerSample() {
+    val adapter = UserPagingAdapter()
+    adapter.addLoadStateListener {
+        // show a retry button outside the list when refresh hits an error
+        retryButton.isVisible = it.refresh is LoadState.Error
+
+        // swipeRefreshLayout displays whether refresh is occurring
+        swipeRefreshLayout.isRefreshing = it.refresh is LoadState.Loading
+
+        // show an empty state over the list when loading initially, before items are loaded
+        emptyState.isVisible = it.refresh is LoadState.Loading && adapter.itemCount == 0
+    }
+}
+
+internal val lifecycleScope = CoroutineScope(Dispatchers.Default)
+
+@Sampled
+@OptIn(ExperimentalCoroutinesApi::class)
+fun loadStateFlowSample() {
+    val adapter = UserPagingAdapter()
+    lifecycleScope.launch {
+        adapter.loadStateFlow
+            .map { it.refresh }
+            .distinctUntilChanged()
+            .collectLatest {
+                // show a retry button outside the list when refresh hits an error
+                retryButton.isVisible = it is LoadState.Error
+
+                // swipeRefreshLayout displays whether refresh is occurring
+                swipeRefreshLayout.isRefreshing = it is LoadState.Loading
+
+                // show an empty state over the list when loading initially, before items are loaded
+                emptyState.isVisible = it is LoadState.Loading && adapter.itemCount == 0
+            }
+    }
+}
+
+@Sampled
+@OptIn(ExperimentalCoroutinesApi::class)
 fun submitDataFlowSample() {
     class MyFlowActivity : AppCompatActivity() {
         val pagingAdapter = UserPagingAdapter()
 
-        @OptIn(ExperimentalCoroutinesApi::class)
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             val viewModel by viewModels<UserListViewModel>()
diff --git a/palette/palette/api/res-1.0.0.txt b/palette/palette/api/res-1.0.0.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/palette/palette/api/res-1.0.0.txt
diff --git a/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt b/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
index 2246db6..7c2c2da 100644
--- a/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
+++ b/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
@@ -20,7 +20,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.assertThrows
 import androidx.testutils.fail
 import com.google.common.truth.Truth.assertThat
@@ -35,9 +34,10 @@
 @LargeTest
 class PreferenceGroupTest {
 
+    @Suppress("DEPRECATION")
     @JvmField
     @Rule
-    val rule = ActivityTestRule(PreferenceTestHelperActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule(PreferenceTestHelperActivity::class.java)
     private val context = ApplicationProvider.getApplicationContext() as android.content.Context
     private lateinit var preferenceGroup: PreferenceGroup
 
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceDialogFragmentCompatTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceDialogFragmentCompatTest.kt
index 258681a..4d4d373 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceDialogFragmentCompatTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceDialogFragmentCompatTest.kt
@@ -31,7 +31,6 @@
 import androidx.preference.test.R
 import androidx.preference.tests.helpers.PreferenceTestHelperActivity
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Rule
 import org.junit.Test
@@ -53,8 +52,11 @@
         }
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(PreferenceTestHelperActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule(
+        PreferenceTestHelperActivity::class.java
+    )
 
     @Test
     fun testInflatedChildDialogFragment() {
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
index 3c15cdd..ff857640 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
@@ -35,7 +35,6 @@
 import androidx.test.espresso.matcher.ViewMatchers.withText
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertNotNull
@@ -52,8 +51,9 @@
 @LargeTest
 class PreferenceViewHolderStateTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(PreferenceTestHelperActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(PreferenceTestHelperActivity::class.java)
 
     private lateinit var fragment: PreferenceFragmentCompat
 
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
index cf2753b..ab4f856 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
@@ -38,7 +38,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import org.hamcrest.Description
 import org.hamcrest.Matchers.allOf
 import org.hamcrest.Matchers.not
@@ -55,8 +54,9 @@
 @LargeTest
 class SeekBarPreferenceTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(PreferenceTestHelperActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(PreferenceTestHelperActivity::class.java)
 
     private lateinit var seekBarPreference: SeekBarPreference
 
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/SelectableTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/SelectableTest.kt
index edf65af..eac2dd5 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/SelectableTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/SelectableTest.kt
@@ -36,7 +36,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -54,8 +53,9 @@
 @LargeTest
 class SelectableTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(PreferenceTestHelperActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(PreferenceTestHelperActivity::class.java)
 
     private lateinit var fragment: PreferenceFragmentCompat
 
diff --git a/preference/preference/src/main/java/androidx/preference/PreferenceDialogFragmentCompat.java b/preference/preference/src/main/java/androidx/preference/PreferenceDialogFragmentCompat.java
index 850cd0e..fbf4b728 100644
--- a/preference/preference/src/main/java/androidx/preference/PreferenceDialogFragmentCompat.java
+++ b/preference/preference/src/main/java/androidx/preference/PreferenceDialogFragmentCompat.java
@@ -134,16 +134,15 @@
     @Override
     public @NonNull
     Dialog onCreateDialog(Bundle savedInstanceState) {
-        final Context context = getActivity();
         mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
 
-        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
                 .setTitle(mDialogTitle)
                 .setIcon(mDialogIcon)
                 .setPositiveButton(mPositiveButtonText, this)
                 .setNegativeButton(mNegativeButtonText, this);
 
-        View contentView = onCreateDialogView(context);
+        View contentView = onCreateDialogView(getContext());
         if (contentView != null) {
             onBindDialogView(contentView);
             builder.setView(contentView);
diff --git a/preference/preference/src/main/java/androidx/preference/PreferenceFragmentCompat.java b/preference/preference/src/main/java/androidx/preference/PreferenceFragmentCompat.java
index ab8bc4f..cf69377 100644
--- a/preference/preference/src/main/java/androidx/preference/PreferenceFragmentCompat.java
+++ b/preference/preference/src/main/java/androidx/preference/PreferenceFragmentCompat.java
@@ -140,13 +140,13 @@
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         final TypedValue tv = new TypedValue();
-        getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
+        getContext().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
         int theme = tv.resourceId;
         if (theme == 0) {
             // Fallback to default theme.
             theme = R.style.PreferenceThemeOverlay;
         }
-        getActivity().getTheme().applyStyle(theme, false);
+        getContext().getTheme().applyStyle(theme, false);
 
         mPreferenceManager = new PreferenceManager(getContext());
         mPreferenceManager.setOnNavigateToScreenListener(this);
@@ -402,8 +402,8 @@
                 handled = ((OnPreferenceStartFragmentCallback) getCallbackFragment())
                         .onPreferenceStartFragment(this, preference);
             }
-            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback) {
-                handled = ((OnPreferenceStartFragmentCallback) getActivity())
+            if (!handled && getContext() instanceof OnPreferenceStartFragmentCallback) {
+                handled = ((OnPreferenceStartFragmentCallback) getContext())
                         .onPreferenceStartFragment(this, preference);
             }
             if (!handled) {
@@ -449,8 +449,8 @@
             handled = ((OnPreferenceStartScreenCallback) getCallbackFragment())
                     .onPreferenceStartScreen(this, preferenceScreen);
         }
-        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
-            ((OnPreferenceStartScreenCallback) getActivity())
+        if (!handled && getContext() instanceof OnPreferenceStartScreenCallback) {
+            ((OnPreferenceStartScreenCallback) getContext())
                     .onPreferenceStartScreen(this, preferenceScreen);
         }
     }
@@ -583,8 +583,8 @@
             handled = ((OnPreferenceDisplayDialogCallback) getCallbackFragment())
                     .onPreferenceDisplayDialog(this, preference);
         }
-        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
-            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
+        if (!handled && getContext() instanceof OnPreferenceDisplayDialogCallback) {
+            handled = ((OnPreferenceDisplayDialogCallback) getContext())
                     .onPreferenceDisplayDialog(this, preference);
         }
 
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
index ff3f964..8a87443 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
@@ -27,7 +27,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -45,8 +44,9 @@
     @get:Rule
     val benchmarkRule = BenchmarkRule()
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(RecyclerViewActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(RecyclerViewActivity::class.java)
 
     @Before
     fun setup() {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
index 3468c5e..950031d 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
@@ -21,7 +21,6 @@
 import android.view.ViewGroup
 import android.widget.TextView
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import org.hamcrest.CoreMatchers.`is`
 import org.junit.Assert
 import org.junit.Assert.assertThat
@@ -36,8 +35,9 @@
 @RunWith(JUnit4::class)
 class RecyclerViewSmoothScrollToPositionTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val mActivityTestRule = ActivityTestRule(TestContentViewActivity::class.java)
+    val mActivityTestRule = androidx.test.rule.ActivityTestRule(TestContentViewActivity::class.java)
 
     @Test
     @Throws(Throwable::class)
diff --git a/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinClassMetadataUtils.kt b/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinClassMetadataUtils.kt
index 9b2071a..955c5f1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinClassMetadataUtils.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.kotlin
 
+import kotlinx.metadata.ClassName
 import kotlinx.metadata.Flag
 import kotlinx.metadata.Flags
 import kotlinx.metadata.KmClassVisitor
@@ -127,4 +128,16 @@
             }
         }
     }
+}
+
+internal fun KotlinClassMetadata.Class.isObject(): Boolean = ObjectReader().let {
+    this@isObject.accept(it)
+    it.isObject
+}
+
+private class ObjectReader() : KmClassVisitor() {
+    var isObject: Boolean = false
+    override fun visit(flags: Flags, name: ClassName) {
+        isObject = Flag.Class.IS_OBJECT(flags)
+    }
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinMetadataElement.kt b/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinMetadataElement.kt
index e35ff96..6d121bc 100644
--- a/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinMetadataElement.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/kotlin/KotlinMetadataElement.kt
@@ -61,6 +61,8 @@
         it.descriptor == method.descriptor
     }?.isSuspend() ?: false
 
+    fun isObject(): Boolean = classMetadata.isObject()
+
     companion object {
 
         /**
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
index 16f4736..9be4658 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
@@ -22,6 +22,7 @@
 import androidx.room.ext.hasAnyOf
 import androidx.room.ext.toAnnotationBox
 import androidx.room.ext.typeName
+import androidx.room.kotlin.KotlinMetadataElement
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_BAD_RETURN_TYPE
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_EMPTY_CLASS
 import androidx.room.processor.ProcessorErrors.TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
@@ -68,8 +69,10 @@
                 .filterValues { it.size > 1 }
                 .values.forEach {
                     it.forEach { converter ->
-                        context.logger.e(converter.method, ProcessorErrors
-                                .duplicateTypeConverters(it.minus(converter)))
+                        context.logger.e(
+                            converter.method, ProcessorErrors
+                                .duplicateTypeConverters(it.minus(converter))
+                        )
                     }
                 }
         }
@@ -78,7 +81,7 @@
     fun process(): List<CustomTypeConverter> {
         // using element utils instead of MoreElements to include statics.
         val methods = ElementFilter
-                .methodsIn(context.processingEnv.elementUtils.getAllMembers(element))
+            .methodsIn(context.processingEnv.elementUtils.getAllMembers(element))
         val declaredType = MoreTypes.asDeclared(element.asType())
         val converterMethods = methods.filter {
             it.hasAnnotation(TypeConverter::class)
@@ -86,30 +89,47 @@
         context.checker.check(converterMethods.isNotEmpty(), element, TYPE_CONVERTER_EMPTY_CLASS)
         val allStatic = converterMethods.all { it.modifiers.contains(Modifier.STATIC) }
         val constructors = ElementFilter.constructorsIn(
-                context.processingEnv.elementUtils.getAllMembers(element))
-        context.checker.check(allStatic || constructors.isEmpty() || constructors.any {
-            it.parameters.isEmpty()
-        }, element, TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR)
-        return converterMethods.mapNotNull { processMethod(declaredType, it) }
+            context.processingEnv.elementUtils.getAllMembers(element)
+        )
+        val kotlinMetadata = KotlinMetadataElement.createFor(context, element)
+        val isKotlinObjectDeclaration = kotlinMetadata?.isObject() == true
+        context.checker.check(
+            isKotlinObjectDeclaration || allStatic || constructors.isEmpty() ||
+                    constructors.any {
+                        it.parameters.isEmpty()
+                    }, element, TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
+        )
+        return converterMethods.mapNotNull {
+            processMethod(
+                container = declaredType,
+                isContainerKotlinObject = isKotlinObjectDeclaration,
+                methodElement = it
+            )
+        }
     }
 
     private fun processMethod(
         container: DeclaredType,
-        methodElement: ExecutableElement
+        methodElement: ExecutableElement,
+        isContainerKotlinObject: Boolean
     ): CustomTypeConverter? {
         val asMember = context.processingEnv.typeUtils.asMemberOf(container, methodElement)
         val executableType = MoreTypes.asExecutable(asMember)
         val returnType = executableType.returnType
         val invalidReturnType = INVALID_RETURN_TYPES.contains(returnType.kind)
-        context.checker.check(methodElement.hasAnyOf(Modifier.PUBLIC), methodElement,
-                TYPE_CONVERTER_MUST_BE_PUBLIC)
+        context.checker.check(
+            methodElement.hasAnyOf(Modifier.PUBLIC), methodElement,
+            TYPE_CONVERTER_MUST_BE_PUBLIC
+        )
         if (invalidReturnType) {
             context.logger.e(methodElement, TYPE_CONVERTER_BAD_RETURN_TYPE)
             return null
         }
         val returnTypeName = returnType.typeName()
-        context.checker.notUnbound(returnTypeName, methodElement,
-                TYPE_CONVERTER_UNBOUND_GENERIC)
+        context.checker.notUnbound(
+            returnTypeName, methodElement,
+            TYPE_CONVERTER_UNBOUND_GENERIC
+        )
         val params = methodElement.parameters
         if (params.size != 1) {
             context.logger.e(methodElement, TYPE_CONVERTER_MUST_RECEIVE_1_PARAM)
@@ -119,7 +139,13 @@
             MoreTypes.asMemberOf(context.processingEnv.typeUtils, container, it)
         }.first()
         context.checker.notUnbound(param.typeName(), params[0], TYPE_CONVERTER_UNBOUND_GENERIC)
-        return CustomTypeConverter(container, methodElement, param, returnType)
+        return CustomTypeConverter(
+            enclosingClass = container,
+            isEnclosingClassKotlinObject = isContainerKotlinObject,
+            method = methodElement,
+            from = param,
+            to = returnType
+        )
     }
 
     /**
@@ -130,6 +156,7 @@
         val converters: List<CustomTypeConverterWrapper>
     ) {
         object EMPTY : ProcessResult(LinkedHashSet(), emptyList())
+
         operator fun plus(other: ProcessResult): ProcessResult {
             val newClasses = LinkedHashSet<TypeMirror>()
             newClasses.addAll(classes)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
index 6196041..90bef99 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
@@ -34,7 +34,11 @@
 
     override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
         scope.builder().apply {
-            if (custom.isStatic) {
+            if (custom.isEnclosingClassKotlinObject) {
+                addStatement("$L = $T.INSTANCE.$L($L)",
+                    outputVarName, custom.typeName,
+                    custom.methodName, inputVarName)
+            } else if (custom.isStatic) {
                 addStatement("$L = $T.$L($L)",
                         outputVarName, custom.typeName,
                         custom.methodName, inputVarName)
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/CustomTypeConverter.kt b/room/compiler/src/main/kotlin/androidx/room/vo/CustomTypeConverter.kt
index 1686b1c..3d214d5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/CustomTypeConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/CustomTypeConverter.kt
@@ -27,12 +27,13 @@
  * Generated when we parse a method annotated with TypeConverter.
  */
 data class CustomTypeConverter(
-    val type: TypeMirror,
+    val enclosingClass: TypeMirror,
+    val isEnclosingClassKotlinObject: Boolean,
     val method: ExecutableElement,
     val from: TypeMirror,
     val to: TypeMirror
 ) {
-    val typeName: TypeName by lazy { type.typeName() }
+    val typeName: TypeName by lazy { enclosingClass.typeName() }
     val fromTypeName: TypeName by lazy { from.typeName() }
     val toTypeName: TypeName by lazy { to.typeName() }
     val methodName by lazy { method.simpleName.toString() }
diff --git a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
index 7df6ff8..5d89402 100644
--- a/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/kotlin/KotlinMetadataElementTest.kt
@@ -25,6 +25,7 @@
 import org.junit.runners.JUnit4
 import simpleRun
 import javax.lang.model.util.ElementFilter
+import kotlin.reflect.KClass
 
 @RunWith(JUnit4::class)
 class KotlinMetadataElementTest {
@@ -32,56 +33,71 @@
     @Test
     fun getParameterNames() {
         simpleRun { invocation ->
-            val (testClassElement, metadataElement) = getMetadataElement(invocation)
+            val (testClassElement, metadataElement) = getMetadataElement(
+                invocation,
+                TestData::class
+            )
             assertThat(ElementFilter.methodsIn(testClassElement.enclosedElements)
                 .first { it.simpleName.toString() == "functionWithParams" }
                 .let { metadataElement.getParameterNames(MoreElements.asExecutable(it)) }
             ).isEqualTo(
                 listOf("param1", "yesOrNo", "number")
             )
-        }
+        }.compilesWithoutError()
     }
 
     @Test
     fun findPrimaryConstructorSignature() {
         simpleRun { invocation ->
-            val (testClassElement, metadataElement) = getMetadataElement(invocation)
+            val (testClassElement, metadataElement) = getMetadataElement(
+                invocation,
+                TestData::class
+            )
             assertThat(
                 ElementFilter.constructorsIn(testClassElement.enclosedElements).map {
                     val desc = MoreElements.asExecutable(it).descriptor()
                     desc to (desc == metadataElement.findPrimaryConstructorSignature())
-                }.toSet()
-            ).isEqualTo(
-                setOf(
-                    "TestData(Ljava/lang/String;)Landroidx/room/kotlin/" +
-                            "KotlinMetadataElementTest\$TestData" to true,
-                    "TestData(Landroidx/room/kotlin/KotlinMetadataElementTest\$TestData" to false
-                )
+                }
+            ).containsExactly(
+                "<init>(Ljava/lang/String;)V" to true,
+                "<init>()V" to false
             )
-        }
+        }.compilesWithoutError()
     }
 
     @Test
     fun isSuspendFunction() {
         simpleRun { invocation ->
-            val (testClassElement, metadataElement) = getMetadataElement(invocation)
-            assertThat(ElementFilter.constructorsIn(testClassElement.enclosedElements).map {
+            val (testClassElement, metadataElement) = getMetadataElement(
+                invocation,
+                TestData::class
+            )
+            assertThat(ElementFilter.methodsIn(testClassElement.enclosedElements).map {
                 val executableElement = MoreElements.asExecutable(it)
                 executableElement.simpleName.toString() to metadataElement.isSuspendFunction(
                     executableElement
                 )
-            }.toSet()).isEqualTo(
-                setOf(
-                    "emptyFunction" to false,
-                    "suspendFunction" to true,
-                    "functionWithParams" to false
-                )
+            }).containsExactly(
+                "emptyFunction" to false,
+                "suspendFunction" to true,
+                "functionWithParams" to false,
+                "getConstructorParam" to false
             )
-        }
+        }.compilesWithoutError()
     }
 
-    private fun getMetadataElement(invocation: TestInvocation) =
-        invocation.typeElement(TestData::class.java.canonicalName!!).let {
+    @Test
+    fun isObject() {
+        simpleRun { invocation ->
+            val (_, objectTypeMetadata) = getMetadataElement(invocation, ObjectType::class)
+            assertThat(objectTypeMetadata.isObject()).isTrue()
+            val (_, testDataMetadata) = getMetadataElement(invocation, TestData::class)
+            assertThat(testDataMetadata.isObject()).isFalse()
+        }.compilesWithoutError()
+    }
+
+    private fun getMetadataElement(invocation: TestInvocation, klass: KClass<*>) =
+        invocation.typeElement(klass.java.canonicalName!!).let {
             it to KotlinMetadataElement.createFor(Context(invocation.processingEnv), it)!!
         }
 
@@ -95,6 +111,11 @@
         suspend fun suspendFunction() {}
 
         @Suppress("UNUSED_PARAMETER")
-        fun functionWithParams(param1: String, yesOrNo: Boolean, number: Int) {}
+        fun functionWithParams(param1: String, yesOrNo: Boolean, number: Int) {
+        }
+    }
+
+    object ObjectType {
+        val foo: String = ""
     }
 }
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/DateConverter.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/DateConverter.kt
index 9c43efc..3d1e23c 100755
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/DateConverter.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/DateConverter.kt
@@ -19,7 +19,7 @@
 import androidx.room.TypeConverter
 import java.util.Date
 
-class DateConverter {
+object DateConverter {
     @TypeConverter
     fun toDate(timestamp: Long?): Date? {
         return if (timestamp == null) null else Date(timestamp)
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/UserDao.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/UserDao.java
index 449f2b5..652b3da 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/UserDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/UserDao.java
@@ -320,6 +320,10 @@
     @Query("UPDATE user SET mName = :name, mLastName = :name WHERE mId = :userId")
     public abstract void setSameNames(String name, int userId);
 
+    @Query("SELECT us.mName, us.mLastName  FROM User as us WHERE mName = :name UNION "
+            + "SELECT us.mName, us.mLastName  FROM User as us WHERE mName = :name")
+    public abstract List<NameAndLastName> selectByName_withTablePrefixAndUnion(String name);
+
     @Query("SELECT mName FROM User")
     public abstract List<NameAndUsers> getNameAndUsers();
 }
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/SimpleEntityReadWriteTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/SimpleEntityReadWriteTest.java
index 8530604..2a0d33e 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/SimpleEntityReadWriteTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/SimpleEntityReadWriteTest.java
@@ -57,6 +57,7 @@
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;
 
+import org.hamcrest.CoreMatchers;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -717,6 +718,18 @@
         assertThat(result.getLastName(), is("same"));
     }
 
+    @Test
+    public void projectionWithTablePrefix() {
+        User user1 = TestUtil.createUser(1);
+        mUserDao.insert(user1);
+        List<NameAndLastName> read = mUserDao.selectByName_withTablePrefixAndUnion(user1.getName());
+        NameAndLastName expected = new NameAndLastName(
+                user1.getName(),
+                user1.getLastName()
+        );
+        assertThat(read, CoreMatchers.equalTo(Arrays.asList(expected)));
+    }
+
     private Set<Day> toSet(Day... days) {
         return new HashSet<>(Arrays.asList(days));
     }
diff --git a/room/runtime/src/main/java/androidx/room/util/CursorUtil.java b/room/runtime/src/main/java/androidx/room/util/CursorUtil.java
index 05b8c59..09da6e2 100644
--- a/room/runtime/src/main/java/androidx/room/util/CursorUtil.java
+++ b/room/runtime/src/main/java/androidx/room/util/CursorUtil.java
@@ -18,9 +18,14 @@
 
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.os.Build;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.Arrays;
 
 /**
  * Cursor utilities for Room
@@ -84,11 +89,15 @@
      * @return The index of the column, or -1 if not found.
      */
     public static int getColumnIndex(@NonNull Cursor c, @NonNull String name) {
-        final int index = c.getColumnIndex(name);
+        int index = c.getColumnIndex(name);
         if (index >= 0) {
             return index;
         }
-        return c.getColumnIndex("`" + name + "`");
+        index = c.getColumnIndex("`" + name + "`");
+        if (index >= 0) {
+            return index;
+        }
+        return findColumnIndexBySuffix(c, name);
     }
 
     /**
@@ -101,11 +110,56 @@
      * @throws IllegalArgumentException if the column does not exist.
      */
     public static int getColumnIndexOrThrow(@NonNull Cursor c, @NonNull String name) {
-        final int index = c.getColumnIndex(name);
+        final int index = getColumnIndex(c, name);
         if (index >= 0) {
             return index;
         }
-        return c.getColumnIndexOrThrow("`" + name + "`");
+        String availableColumns = "";
+        try {
+            availableColumns = Arrays.toString(c.getColumnNames());
+        } catch (Exception e) {
+            Log.d("RoomCursorUtil", "Cannot collect column names for debug purposes", e);
+        }
+        throw new IllegalArgumentException("column '" + name
+                + "' does not exist. Available columns: " + availableColumns);
+    }
+
+    /**
+     * Finds a column by name by appending `.` in front of it and checking by suffix match.
+     * Also checks for the version wrapped with `` (backticks).
+     * workaround for b/157261134 for API levels 25 and below
+     *
+     * e.g. "foo" will match "any.foo" and "`any.foo`"
+     */
+    private static int findColumnIndexBySuffix(@NonNull Cursor cursor, @NonNull String name) {
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
+            // we need this workaround only on APIs < 26. So just return not found on newer APIs
+            return -1;
+        }
+        if (name.length() == 0) {
+            return -1;
+        }
+        final String[] columnNames = cursor.getColumnNames();
+        return findColumnIndexBySuffix(columnNames, name);
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    static int findColumnIndexBySuffix(String[] columnNames, String name) {
+        String dotSuffix = "." + name;
+        String backtickSuffix = "." + name + "`";
+        for (int index = 0; index < columnNames.length; index++) {
+            String columnName = columnNames[index];
+            // do not check if column name is not long enough. 1 char for table name, 1 char for '.'
+            if (columnName.length() >= name.length() + 2) {
+                if (columnName.endsWith(dotSuffix)) {
+                    return index;
+                } else if (columnName.charAt(0) == '`'
+                        && columnName.endsWith(backtickSuffix)) {
+                    return index;
+                }
+            }
+        }
+        return -1;
     }
 
     private CursorUtil() {
diff --git a/room/runtime/src/test/java/androidx/room/util/CursorUtilTest.kt b/room/runtime/src/test/java/androidx/room/util/CursorUtilTest.kt
new file mode 100644
index 0000000..6c57aef
--- /dev/null
+++ b/room/runtime/src/test/java/androidx/room/util/CursorUtilTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.util
+
+import androidx.room.util.CursorUtil.findColumnIndexBySuffix
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class CursorUtilTest {
+    @Test
+    fun findColumnIndex_simple() {
+        assertThat(
+            findColumnIndexBySuffix(
+                arrayOf("a.b"),
+                "b"
+            )
+        ).isEqualTo(0)
+    }
+
+    @Test
+    fun findColumnIndex_emptyList() {
+        assertThat(
+            findColumnIndexBySuffix(
+                emptyArray(),
+                "b"
+            )
+        ).isEqualTo(-1)
+    }
+
+    @Test
+    fun findColumnIndex_tooShort() {
+        assertThat(
+            findColumnIndexBySuffix(
+                arrayOf("b"),
+                "b"
+            )
+        ).isEqualTo(-1)
+    }
+
+    @Test
+    fun findColumnIndex_backTick() {
+        assertThat(
+            findColumnIndexBySuffix(
+                arrayOf("`a.b`"),
+                "b"
+            )
+        ).isEqualTo(0)
+    }
+
+    @Test
+    fun findColumnIndex_backTick_missingFirstTick() {
+        assertThat(
+            findColumnIndexBySuffix(
+                arrayOf("a.b`"),
+                "b"
+            )
+        ).isEqualTo(-1)
+    }
+}
\ No newline at end of file
diff --git a/samples/SupportSliceDemos/OWNERS b/samples/SupportSliceDemos/OWNERS
index 921a517..c60f11f 100644
--- a/samples/SupportSliceDemos/OWNERS
+++ b/samples/SupportSliceDemos/OWNERS
@@ -1,2 +1,4 @@
 jmonk@google.com
 madym@google.com
+pinyaoting@google.com
+sunnygoyal@google.com
diff --git a/samples/SupportSliceDemos/src/main/res/values/styles.xml b/samples/SupportSliceDemos/src/main/res/values/styles.xml
index cb1dd13..a6f5f2a 100644
--- a/samples/SupportSliceDemos/src/main/res/values/styles.xml
+++ b/samples/SupportSliceDemos/src/main/res/values/styles.xml
@@ -24,6 +24,7 @@
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
         <item name="sliceViewStyle">@style/CustomSliceView</item>
+        <item name="rowStyle">@style/CustomRowStyle</item>
     </style>
 
     <style name="AppTheme.NoActionBar">
@@ -39,4 +40,10 @@
         <item name="android:paddingEnd">16dp</item>
         <item name="android:paddingStart">16dp</item>
     </style>
+
+    <style name="CustomRowStyle">
+        <item name="progressBarInlineWidth">229dp</item>
+        <item name="progressBarStartPadding">12dp</item>
+        <item name="progressBarEndPadding">16dp</item>
+    </style>
 </resources>
diff --git a/security/crypto/src/androidTest/java/androidx/security/crypto/EncryptedSharedPreferencesTest.java b/security/crypto/src/androidTest/java/androidx/security/crypto/EncryptedSharedPreferencesTest.java
index dc80a78..b5f9d2e 100644
--- a/security/crypto/src/androidTest/java/androidx/security/crypto/EncryptedSharedPreferencesTest.java
+++ b/security/crypto/src/androidTest/java/androidx/security/crypto/EncryptedSharedPreferencesTest.java
@@ -335,6 +335,17 @@
         Assert.assertEquals("Data should not exist", null,
                 sharedPreferences.getString(twiceKey, null));
 
+        editor.clear();
+        editor.commit();
+
+        // test clear after put with apply
+        editor.putString("New Data", "New");
+        editor.apply();
+        editor.clear();
+        editor.apply();
+
+        Assert.assertEquals("Get all size should be equal", 0,
+                sharedPreferences.getAll().size());
     }
 
     @Test
diff --git a/security/crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java b/security/crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
index 80a1320..45734da 100644
--- a/security/crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
+++ b/security/crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
@@ -346,6 +346,7 @@
             clearKeysIfNeeded();
             mEditor.apply();
             notifyListeners();
+            mKeysChanged.clear();
         }
 
         private void clearKeysIfNeeded() {
diff --git a/settings.gradle b/settings.gradle
index 3743d2b..0baccbf 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -320,6 +320,8 @@
 includeProject(":viewpager2:viewpager2", "viewpager2/viewpager2")
 includeProject(":viewpager2:integration-tests:testapp", "viewpager2/integration-tests/testapp")
 includeProject(":wear:wear", "wear/wear")
+includeProject(":wear:wear-input", "wear/wear-input")
+includeProject(":wear:wear-input-testing", "wear/wear-input-testing")
 includeProject(":webkit:webkit", "webkit/webkit")
 includeProject(":webkit:integration-tests:testapp", "webkit/integration-tests/testapp")
 includeProject(":window:window", "window/window")
diff --git a/slices/test/src/main/java/androidx/slice/test/SampleSliceProvider.java b/slices/test/src/main/java/androidx/slice/test/SampleSliceProvider.java
index faeca79..dd492e2f 100644
--- a/slices/test/src/main/java/androidx/slice/test/SampleSliceProvider.java
+++ b/slices/test/src/main/java/androidx/slice/test/SampleSliceProvider.java
@@ -98,6 +98,7 @@
             "gallery",
             "indeterminaterange",
             "indeterminaterange2",
+            "indeterminaterange3",
             "weather",
             "reservation",
             "loadlist",
@@ -167,6 +168,8 @@
                 return createIndeterminateProgressRange(sliceUri);
             case "/indeterminaterange2":
                 return createIndeterminateProgressRange2(sliceUri);
+            case "/indeterminaterange3":
+                return createIndeterminateProgressRange3(sliceUri);
             case "/ride":
                 return createRideSlice(sliceUri);
             case "/toggle":
@@ -895,6 +898,41 @@
                 .build();
     }
 
+    private Slice createIndeterminateProgressRange3(Uri sliceUri) {
+        IconCompat thumbIcon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
+        IconCompat titleIcon = IconCompat.createWithResource(getContext(), R.drawable.ic_car);
+        IconCompat checkBoxIcon = IconCompat.createWithResource(getContext(),
+                R.drawable.toggle_check);
+        SliceAction primaryAction = SliceAction.create(
+                getBroadcastIntent(ACTION_TOAST, "open rich star rating"), thumbIcon, ICON_IMAGE,
+                "Rate");
+        IconCompat icon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
+        SliceAction progressPrimaryAction = SliceAction.create(
+                getBroadcastIntent(ACTION_TOAST, "open download"), icon, ICON_IMAGE,
+                "Download");
+        return new ListBuilder(getContext(), sliceUri, INFINITY)
+                .setAccentColor(0xff4285f4)
+                .addInputRange(new InputRangeBuilder()
+                        .setTitleItem(titleIcon, ListBuilder.ICON_IMAGE)
+                        .addEndItem(SliceAction.createToggle(
+                                getBroadcastIntent(ACTION_TOAST, "click checkbox"), checkBoxIcon,
+                                "checkbox", false))
+                        .setTitle("Rich star rating")
+                        .setMin(5)
+                        .setThumb(thumbIcon)
+                        .setInputAction(getBroadcastIntent(ACTION_TOAST_RANGE_VALUE, null))
+                        .setMax(100)
+                        .setValue(sStarRating)
+                        .setPrimaryAction(primaryAction)
+                        .setContentDescription("Slider for star ratings"))
+                .addRange(new RangeBuilder()
+                        .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+                        .setMode(ListBuilder.RANGE_MODE_INDETERMINATE)
+                        .setTitle("Indeterminate progress")
+                        .setPrimaryAction(progressPrimaryAction))
+                .build();
+    }
+
     private Slice createToggleTesterSlice(Uri uri) {
         IconCompat star = IconCompat.createWithResource(getContext(), R.drawable.toggle_star);
         IconCompat icon = IconCompat.createWithResource(getContext(), R.drawable.ic_star_on);
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowStyle.java b/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
index e06977d..8bd56f8 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
@@ -46,6 +46,10 @@
     private int mBottomDividerEndPadding;
     private int mActionDividerHeight;
     private int mSeekBarInlineWidth;
+    private int mProgressBarInlineWidth;
+    private int mProgressBarStartPadding;
+    private int mProgressBarEndPadding;
+    private int mIconSize;
 
     public RowStyle(Context context, int resId) {
         TypedArray a = context.getTheme().obtainStyledAttributes(resId, R.styleable.RowStyle);
@@ -78,6 +82,14 @@
                     R.styleable.RowStyle_actionDividerHeight, UNBOUNDED);
             mSeekBarInlineWidth = (int) a.getDimension(
                     R.styleable.RowStyle_seekBarInlineWidth, UNBOUNDED);
+            mProgressBarInlineWidth = (int) a.getDimension(
+                    R.styleable.RowStyle_progressBarInlineWidth, UNBOUNDED);
+            mProgressBarStartPadding = (int) a.getDimension(
+                    R.styleable.RowStyle_progressBarStartPadding, UNBOUNDED);
+            mProgressBarEndPadding = (int) a.getDimension(
+                    R.styleable.RowStyle_progressBarEndPadding, UNBOUNDED);
+            mIconSize = (int) a.getDimension(
+                    R.styleable.RowStyle_iconSize, UNBOUNDED);
         } finally {
             a.recycle();
         }
@@ -138,4 +150,20 @@
     public int getSeekBarInlineWidth() {
         return mSeekBarInlineWidth;
     }
+
+    public int getProgressBarInlineWidth() {
+        return mProgressBarInlineWidth;
+    }
+
+    public int getProgressBarStartPadding() {
+        return mProgressBarStartPadding;
+    }
+
+    public int getProgressBarEndPadding() {
+        return mProgressBarEndPadding;
+    }
+
+    public int getIconSize() {
+        return mIconSize;
+    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowView.java b/slices/view/src/main/java/androidx/slice/widget/RowView.java
index 29ced79..e4d09d0 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -725,6 +725,13 @@
             } else {
                 progressBar = (ProgressBar) LayoutInflater.from(getContext()).inflate(
                         R.layout.abc_slice_progress_inline_view, this, false);
+                if (mSliceStyle != null && mSliceStyle.getRowStyle() != null) {
+                    setViewWidth(progressBar,
+                            mSliceStyle.getRowStyle().getProgressBarInlineWidth());
+                    setViewSidePaddings(progressBar,
+                            mSliceStyle.getRowStyle().getProgressBarStartPadding(),
+                            mSliceStyle.getRowStyle().getProgressBarEndPadding());
+                }
             }
             if (isIndeterminate) {
                 progressBar.setIndeterminate(true);
@@ -913,6 +920,10 @@
             lp.height = useIntrinsicSize ? Math.round(d.getIntrinsicHeight() / density) :
                     mImageSize;
             iv.setLayoutParams(lp);
+            if (mSliceStyle != null && mSliceStyle.getRowStyle() != null) {
+                int styleIconSize = mSliceStyle.getRowStyle().getIconSize();
+                mIconSize = styleIconSize > 0 ? styleIconSize : mIconSize;
+            }
             int p = isIcon ? mIconSize / 2 : 0;
             iv.setPadding(p, p, p, p);
             addedView = iv;
diff --git a/slices/view/src/main/res-public/values/public_attrs.xml b/slices/view/src/main/res-public/values/public_attrs.xml
index 48f7d31..0442c73 100644
--- a/slices/view/src/main/res-public/values/public_attrs.xml
+++ b/slices/view/src/main/res-public/values/public_attrs.xml
@@ -50,4 +50,8 @@
     <public type="attr" name="rowRangeHeight" />
     <public type="attr" name="rowRangeSingleTextHeight" />
     <public type="attr" name="seekBarInlineWidth" />
+    <public type="attr" name="progressBarInlineWidth" />
+    <public type="attr" name="progressBarStartPadding" />
+    <public type="attr" name="progressBarEndPadding" />
+    <public type="attr" name="iconSize" />
 </resources>
diff --git a/slices/view/src/main/res/values/attrs.xml b/slices/view/src/main/res/values/attrs.xml
index 343af28..8c16813 100644
--- a/slices/view/src/main/res/values/attrs.xml
+++ b/slices/view/src/main/res/values/attrs.xml
@@ -107,5 +107,15 @@
 
         <!-- Width to use for inline SeekBar in the row. -->
         <attr name="seekBarInlineWidth" format="dimension"/>
+
+        <!-- Width to use for inline progress bar in the row. -->
+        <attr name="progressBarInlineWidth" format="dimension"/>
+        <!-- Padding to the start edge of the progress bar in the row. -->
+        <attr name="progressBarStartPadding" format="dimension" />
+        <!-- Padding to the end edge of the progress bar in the row. -->
+        <attr name="progressBarEndPadding" format="dimension" />
+
+        <!-- Size of icon. -->
+        <attr name="iconSize" format="dimension" />
     </declare-styleable>
 </resources>
\ No newline at end of file
diff --git a/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspectionExecutors.java b/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspectionExecutors.java
index c03a0eb..ceae951 100644
--- a/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspectionExecutors.java
+++ b/sqlite/sqlite-inspection/src/main/java/androidx/sqlite/inspection/SqliteInspectionExecutors.java
@@ -42,7 +42,7 @@
         }
 
         private String generateThreadName() {
-            return String.format(Locale.ROOT, "Studio: SqliteInspector thread-%d",
+            return String.format(Locale.ROOT, "Studio:SqlIns%d",
                     mNextId.getAndIncrement());
         }
     };
diff --git a/testutils/testutils-appcompat/src/main/java/androidx/testutils/RecreatedAppCompatActivity.kt b/testutils/testutils-appcompat/src/main/java/androidx/testutils/RecreatedAppCompatActivity.kt
index b577fc2..ea23c83 100644
--- a/testutils/testutils-appcompat/src/main/java/androidx/testutils/RecreatedAppCompatActivity.kt
+++ b/testutils/testutils-appcompat/src/main/java/androidx/testutils/RecreatedAppCompatActivity.kt
@@ -19,7 +19,6 @@
 import android.os.Bundle
 import androidx.annotation.LayoutRes
 import androidx.appcompat.app.AppCompatActivity
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertTrue
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -70,8 +69,8 @@
  *
  * @return The newly-restarted [RecreatedAppCompatActivity]
  */
-@Suppress("UNCHECKED_CAST")
-fun <T : RecreatedAppCompatActivity> ActivityTestRule<T>.recreate(): T {
+@Suppress("UNCHECKED_CAST", "DEPRECATION")
+fun <T : RecreatedAppCompatActivity> androidx.test.rule.ActivityTestRule<T>.recreate(): T {
     // Now switch the orientation
     RecreatedAppCompatActivity.resumedLatch = CountDownLatch(1)
     RecreatedAppCompatActivity.destroyedLatch = CountDownLatch(1)
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt b/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
index ec1f15e..afc6573 100644
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
+++ b/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
@@ -18,13 +18,13 @@
 
 import android.app.Activity
 import android.os.Looper
-import androidx.test.rule.ActivityTestRule
 
 /**
  * Wait for execution, by default waiting 2 cycles to ensure that posted transitions are
  * executed and have had a chance to run.
  */
-fun ActivityTestRule<out Activity>.waitForExecution(cycles: Int = 2) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out Activity>.waitForExecution(cycles: Int = 2) {
     // Wait for two cycles. When starting a postponed transition, it will post to
     // the UI thread and then the execution will be added onto the queue after that.
     // The two-cycle wait makes sure fragments have the opportunity to complete both
@@ -38,7 +38,8 @@
     }
 }
 
-fun ActivityTestRule<out Activity>.runOnUiThreadRethrow(block: () -> Unit) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out Activity>.runOnUiThreadRethrow(block: () -> Unit) {
     if (Looper.getMainLooper() == Looper.myLooper()) {
         block()
     } else {
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/AnimationActivityTestRule.kt b/testutils/testutils-runtime/src/main/java/androidx/testutils/AnimationActivityTestRule.kt
index 6fa09ec..52b0657 100644
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/AnimationActivityTestRule.kt
+++ b/testutils/testutils-runtime/src/main/java/androidx/testutils/AnimationActivityTestRule.kt
@@ -20,7 +20,6 @@
 import android.animation.ValueAnimator
 import android.annotation.SuppressLint
 import android.os.Build
-import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.intercepting.SingleActivityFactory
 
 import org.junit.runner.Description
@@ -35,7 +34,8 @@
  * Activity (launchActivity = false).
  */
 
-open class AnimationActivityTestRule<T : Activity> : ActivityTestRule<T> {
+@Suppress("DEPRECATION")
+open class AnimationActivityTestRule<T : Activity> : androidx.test.rule.ActivityTestRule<T> {
 
     private enum class TestType {
         NORMAL, // Test without the @AnimationTest
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java b/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java
index 7b73950..9b1b6d5 100644
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java
+++ b/testutils/testutils-runtime/src/main/java/androidx/testutils/LifecycleOwnerUtils.java
@@ -28,7 +28,6 @@
 import androidx.lifecycle.LifecycleEventObserver;
 import androidx.lifecycle.LifecycleOwner;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.ActivityTestRule;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -95,7 +94,8 @@
      */
     @NonNull
     public static <T extends Activity & LifecycleOwner> T waitForRecreation(
-            @NonNull final ActivityTestRule<T> activityRule
+            @SuppressWarnings("deprecation")
+            @NonNull final androidx.test.rule.ActivityTestRule<T> activityRule
     ) throws Throwable {
         return waitForRecreation(activityRule.getActivity());
     }
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/RecreatedActivity.kt b/testutils/testutils-runtime/src/main/java/androidx/testutils/RecreatedActivity.kt
index 8c02fc8..d8eb3bc 100644
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/RecreatedActivity.kt
+++ b/testutils/testutils-runtime/src/main/java/androidx/testutils/RecreatedActivity.kt
@@ -19,7 +19,6 @@
 import android.os.Bundle
 import androidx.annotation.LayoutRes
 import androidx.fragment.app.FragmentActivity
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -70,8 +69,8 @@
  *
  * @return The newly-restarted [RecreatedActivity]
  */
-@Suppress("UNCHECKED_CAST")
-fun <T : RecreatedActivity> ActivityTestRule<T>.recreate(): T {
+@Suppress("UNCHECKED_CAST", "DEPRECATION")
+fun <T : RecreatedActivity> androidx.test.rule.ActivityTestRule<T>.recreate(): T {
     // Now switch the orientation
     RecreatedActivity.resumedLatch = CountDownLatch(1)
     RecreatedActivity.destroyedLatch = CountDownLatch(1)
diff --git a/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt b/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
index ac3fe48..ea867df 100644
--- a/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
+++ b/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.transition.ktx.test.R
 import org.junit.Assert.assertTrue
 import org.junit.Before
@@ -35,7 +34,9 @@
 @SdkSuppress(minSdkVersion = 19)
 @MediumTest
 class TransitionTest {
-    @JvmField @Rule val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    @Suppress("DEPRECATION")
+    @JvmField @Rule
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
 
     private lateinit var transition: Transition
 
diff --git a/transition/transition/src/androidTest/java/androidx/transition/FragmentTestUtil.kt b/transition/transition/src/androidTest/java/androidx/transition/FragmentTestUtil.kt
index f5c9d31..794a637 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/FragmentTestUtil.kt
+++ b/transition/transition/src/androidTest/java/androidx/transition/FragmentTestUtil.kt
@@ -26,14 +26,14 @@
 import androidx.fragment.app.TargetTracking
 import androidx.transition.test.R
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.runOnUiThreadRethrow
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import java.lang.ref.WeakReference
 import java.util.ArrayList
 
-fun ActivityTestRule<out FragmentActivity>.executePendingTransactions(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.executePendingTransactions(
     fm: FragmentManager = activity.supportFragmentManager
 ): Boolean {
     var ret = false
@@ -41,7 +41,8 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(): Boolean {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(): Boolean {
     val instrumentation = InstrumentationRegistry.getInstrumentation()
     var ret = false
     instrumentation.runOnMainSync {
@@ -50,7 +51,8 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
     id: Int,
     flags: Int = 0
 ): Boolean {
@@ -62,7 +64,8 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.popBackStackImmediate(
     name: String,
     flags: Int = 0
 ): Boolean {
@@ -74,7 +77,10 @@
     return ret
 }
 
-fun ActivityTestRule<out FragmentActivity>.setContentView(@LayoutRes layoutId: Int) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.setContentView(
+    @LayoutRes layoutId: Int
+) {
     val instrumentation = InstrumentationRegistry.getInstrumentation()
     instrumentation.runOnMainSync { activity.setContentView(layoutId) }
 }
@@ -91,16 +97,19 @@
     }
 }
 
+@Suppress("DEPRECATION")
 // Transition test methods start
-fun ActivityTestRule<out FragmentActivity>.findGreen(): View {
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findGreen(): View {
     return activity.findViewById(R.id.greenSquare)
 }
 
-fun ActivityTestRule<out FragmentActivity>.findBlue(): View {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findBlue(): View {
     return activity.findViewById(R.id.blueSquare)
 }
 
-fun ActivityTestRule<out FragmentActivity>.findRed(): View? {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out FragmentActivity>.findRed(): View? {
     return activity.findViewById(R.id.redSquare)
 }
 
@@ -131,20 +140,20 @@
 }
 
 fun verifyNoOtherTransitions(fragment: TransitionFragment) {
-    assertThat(fragment.enterTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.enterTransition.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.exitTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.exitTransition.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.enterTransition.enteringTargets).isEmpty()
+    assertThat(fragment.enterTransition.exitingTargets).isEmpty()
+    assertThat(fragment.exitTransition.enteringTargets).isEmpty()
+    assertThat(fragment.exitTransition.exitingTargets).isEmpty()
 
-    assertThat(fragment.reenterTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.reenterTransition.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.returnTransition.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.returnTransition.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.reenterTransition.enteringTargets).isEmpty()
+    assertThat(fragment.reenterTransition.exitingTargets).isEmpty()
+    assertThat(fragment.returnTransition.enteringTargets).isEmpty()
+    assertThat(fragment.returnTransition.exitingTargets).isEmpty()
 
-    assertThat(fragment.sharedElementEnter.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementEnter.exitingTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementReturn.enteringTargets.size).isEqualTo(0)
-    assertThat(fragment.sharedElementReturn.exitingTargets.size).isEqualTo(0)
+    assertThat(fragment.sharedElementEnter.enteringTargets).isEmpty()
+    assertThat(fragment.sharedElementEnter.exitingTargets).isEmpty()
+    assertThat(fragment.sharedElementReturn.enteringTargets).isEmpty()
+    assertThat(fragment.sharedElementReturn.exitingTargets).isEmpty()
 }
 // Transition test methods end
 
diff --git a/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt b/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
index 0686fa1..f5cd778 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
+++ b/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
@@ -26,7 +26,6 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.waitForExecution
 import androidx.transition.test.R
 import com.google.common.truth.Truth.assertThat
@@ -50,8 +49,11 @@
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
 class FragmentTransitionTest(private val reorderingAllowed: Boolean) {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityRule = ActivityTestRule(FragmentTransitionTestActivity::class.java)
+    val activityRule = androidx.test.rule.ActivityTestRule(
+        FragmentTransitionTestActivity::class.java
+    )
 
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private lateinit var fragmentManager: FragmentManager
diff --git a/tv-provider/tv-provider/src/androidTest/java/androidx/tvprovider/media/tv/PreviewChannelHelperTest.java b/tv-provider/tv-provider/src/androidTest/java/androidx/tvprovider/media/tv/PreviewChannelHelperTest.java
index 1e89a26..ae708c4 100644
--- a/tv-provider/tv-provider/src/androidTest/java/androidx/tvprovider/media/tv/PreviewChannelHelperTest.java
+++ b/tv-provider/tv-provider/src/androidTest/java/androidx/tvprovider/media/tv/PreviewChannelHelperTest.java
@@ -321,6 +321,22 @@
         assertTrue(channelsEqual(builder.build(), channelFromTvProvider));
     }
 
+    @Test
+    public void testPreviewChannelsCreationUsingSameBuilder() throws IOException {
+        if (!Utils.hasTvInputFramework(ApplicationProvider.getApplicationContext())) {
+            return;
+        }
+        PreviewChannelHelper helper = new PreviewChannelHelper(mContext);
+        PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel();
+        long channelId1 = helper.publishDefaultChannel(builder.build());
+        PreviewChannel channelFromTvProvider = getPreviewChannel(helper, channelId1);
+        assertTrue(channelsEqual(builder.build(), channelFromTvProvider));
+        builder.setDescription(null);
+        long channelId2 = helper.publishChannel(builder.build());
+        channelFromTvProvider = getPreviewChannel(helper, channelId2);
+        assertTrue(channelsEqual(builder.build(), channelFromTvProvider));
+    }
+
     /**
      * All this method is actually doing is
      * <pre>
@@ -369,6 +385,7 @@
         assertEquals(4, allChannels.size());
     }
 
+
     /**
      * Test UR of CRUD
      * Test that the PreviewChannelHelper can correctly update and read preview channels.
@@ -577,7 +594,7 @@
         boolean result = channelA.getDisplayName().equals(channelB.getDisplayName())
                 && channelA.getType().equals(channelB.getType())
                 && channelA.getAppLinkIntentUri().equals(channelB.getAppLinkIntentUri())
-                && channelA.getDescription().equals(channelB.getDescription())
+                && Objects.equals(channelA.getDescription(), channelB.getDescription())
                 && channelA.getPackageName().equals(channelB.getPackageName())
                 && channelA.getInternalProviderFlag1() == channelB.getInternalProviderFlag1()
                 && channelA.getInternalProviderFlag2() == channelB.getInternalProviderFlag2()
diff --git a/tv-provider/tv-provider/src/main/java/androidx/tvprovider/media/tv/PreviewChannel.java b/tv-provider/tv-provider/src/main/java/androidx/tvprovider/media/tv/PreviewChannel.java
index 58a7e22..5ef52ab 100644
--- a/tv-provider/tv-provider/src/main/java/androidx/tvprovider/media/tv/PreviewChannel.java
+++ b/tv-provider/tv-provider/src/main/java/androidx/tvprovider/media/tv/PreviewChannel.java
@@ -399,7 +399,9 @@
          */
         @NonNull
         public Builder setDescription(@Nullable CharSequence description) {
-            if (description != null) {
+            if (description == null) {
+                mValues.remove(Channels.COLUMN_DESCRIPTION);
+            } else {
                 mValues.put(Channels.COLUMN_DESCRIPTION, description.toString());
             }
             return this;
diff --git a/ui/gradle/wrapper/gradle-wrapper.properties b/ui/gradle/wrapper/gradle-wrapper.properties
index 2bec472..782da6d 100644
--- a/ui/gradle/wrapper/gradle-wrapper.properties
+++ b/ui/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=../../../../../tools/external/gradle/gradle-6.4-bin.zip
+distributionUrl=../../../../../tools/external/gradle/gradle-6.5-bin.zip
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewBenchmark.kt
new file mode 100644
index 0000000..166fe08
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewBenchmark.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.benchmark.test.view
+
+import androidx.ui.integration.test.view.AndroidTextViewTestCase
+import androidx.test.filters.LargeTest
+import androidx.ui.benchmark.AndroidBenchmarkRule
+import androidx.ui.benchmark.benchmarkDrawPerf
+import androidx.ui.benchmark.benchmarkFirstDraw
+import androidx.ui.benchmark.benchmarkFirstLayout
+import androidx.ui.benchmark.benchmarkFirstMeasure
+import androidx.ui.benchmark.benchmarkFirstSetContent
+import androidx.ui.benchmark.benchmarkLayoutPerf
+import androidx.ui.integration.test.TextBenchmarkTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Benchmark that runs [AndroidTextViewTestCase].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class AndroidTextViewBenchmark(private val textLength: Int) {
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "length={0}")
+        fun initParameters(): Array<Any> = arrayOf(32, 512)
+    }
+
+    @get:Rule
+    val textBenchmarkRule = TextBenchmarkTestRule()
+
+    @get:Rule
+    val benchmarkRule = AndroidBenchmarkRule()
+
+    @Test
+    fun first_setContent() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkFirstSetContent {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+
+    @Test
+    fun first_measure() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkFirstMeasure {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+
+    @Test
+    fun first_layout() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkFirstLayout {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+
+    @Test
+    fun first_draw() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkFirstDraw {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+
+    @Test
+    fun layout() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkLayoutPerf {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+
+    @Test
+    fun draw() {
+        textBenchmarkRule.generator { textGenerator ->
+            benchmarkRule.benchmarkDrawPerf {
+                AndroidTextViewTestCase(textLength, textGenerator)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/text/ParagraphMethodBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/text/ParagraphMethodBenchmark.kt
index f26c660..9b3fb3e 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/text/ParagraphMethodBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/text/ParagraphMethodBenchmark.kt
@@ -20,7 +20,7 @@
 import androidx.benchmark.junit4.measureRepeated
 import androidx.test.filters.LargeTest
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.sp
 import androidx.ui.integration.test.RandomTextGenerator
 import androidx.ui.integration.test.TextBenchmarkTestRule
@@ -164,7 +164,7 @@
     fun getOffsetForPosition() {
         textBenchmarkRule.generator { generator ->
             val paragraph = paragraph(generator)
-            val centerPosition = PxPosition((paragraph.width / 2), (paragraph.height / 2))
+            val centerPosition = Offset(paragraph.width / 2, paragraph.height / 2)
             benchmarkRule.measureRepeated {
                 paragraph.getOffsetForPosition(centerPosition)
             }
diff --git a/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/AndroidBenchmarkRule.kt b/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/AndroidBenchmarkRule.kt
index 74e44d3..296ca22 100644
--- a/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/AndroidBenchmarkRule.kt
+++ b/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/AndroidBenchmarkRule.kt
@@ -19,7 +19,6 @@
 import androidx.activity.ComponentActivity
 import androidx.benchmark.junit4.BenchmarkRule
 import androidx.benchmark.junit4.measureRepeated
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.test.ComposeTestCase
 import androidx.ui.benchmark.android.AndroidTestCase
 import androidx.ui.benchmark.android.AndroidTestCaseRunner
@@ -32,8 +31,9 @@
  */
 class AndroidBenchmarkRule : TestRule {
 
+    @Suppress("DEPRECATION")
     private val activityTestRule =
-        ActivityTestRule<ComponentActivity>(
+        androidx.test.rule.ActivityTestRule<ComponentActivity>(
             ComponentActivity::class.java
         )
 
diff --git a/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/ComposeBenchmarkRule.kt b/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/ComposeBenchmarkRule.kt
index 5fb2a75..212de86 100644
--- a/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/ComposeBenchmarkRule.kt
+++ b/ui/integration-tests/benchmark/src/main/java/androidx/ui/benchmark/ComposeBenchmarkRule.kt
@@ -19,7 +19,6 @@
 import androidx.activity.ComponentActivity
 import androidx.benchmark.junit4.BenchmarkRule
 import androidx.benchmark.junit4.measureRepeated
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.test.ComposeBenchmarkScope
 import androidx.ui.test.ComposeTestCase
 import androidx.ui.test.DisableTransitions
@@ -37,8 +36,9 @@
     private val enableTransitions: Boolean = false
 ) : TestRule {
 
+    @Suppress("DEPRECATION")
     private val activityTestRule =
-        ActivityTestRule<ComponentActivity>(ComponentActivity::class.java)
+        androidx.test.rule.ActivityTestRule<ComponentActivity>(ComponentActivity::class.java)
 
     val benchmarkRule = BenchmarkRule()
 
diff --git a/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedScrollerTestCase.kt b/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedScrollerTestCase.kt
index 4b7a687..c32678d 100644
--- a/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedScrollerTestCase.kt
+++ b/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedScrollerTestCase.kt
@@ -39,7 +39,6 @@
 import androidx.ui.material.MaterialTheme
 import androidx.ui.material.Surface
 import androidx.ui.test.ComposeTestCase
-import androidx.ui.unit.px
 import kotlin.random.Random
 
 /**
@@ -83,22 +82,22 @@
                             val blue = Random.nextInt(256)
                             Color(red = red, green = green, blue = blue)
                         }
-                        Box(Modifier.preferredSize(350.px.toDp()).drawBackground(color))
+                        Box(Modifier.preferredSize(350f.toDp()).drawBackground(color))
                         Text(
                             text = "Some title",
                             color = Color.Black,
-                            fontSize = 60.px.toSp()
+                            fontSize = 60f.toSp()
                         )
                         Row(Modifier.fillMaxWidth()) {
                             Text(
                                 "3.5 ★",
-                                fontSize = 40.px.toSp(),
+                                fontSize = 40.toSp(),
                                 modifier = Modifier.gravity(Alignment.CenterVertically)
                             )
                             Box(
                                 Modifier
                                     .gravity(Alignment.CenterVertically)
-                                    .preferredSize(40.px.toDp())
+                                    .preferredSize(40f.toDp())
                                     .drawBackground(playStoreColor)
                             )
                         }
diff --git a/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewTestCase.kt b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewTestCase.kt
new file mode 100644
index 0000000..7e1014c
--- /dev/null
+++ b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewTestCase.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.integration.test.view
+
+import android.app.Activity
+import android.util.TypedValue
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.ui.benchmark.android.AndroidTestCase
+import androidx.ui.integration.test.RandomTextGenerator
+import kotlin.math.roundToInt
+
+/**
+ * Version of [androidx.ui.integration.test.core.text.TextBasicTestCase] using Android views.
+ */
+class AndroidTextViewTestCase(
+    val textLength: Int,
+    val randomTextGenerator: RandomTextGenerator
+) : AndroidTestCase {
+
+    private var fontSize = 8f
+
+    override fun getContent(activity: Activity): ViewGroup {
+        val linearLayout = LinearLayout(activity)
+        val textView = TextView(activity)
+        textView.text = randomTextGenerator.nextParagraph(textLength)
+        textView.layoutParams = LinearLayout.LayoutParams(
+            ViewGroup.LayoutParams.WRAP_CONTENT,
+            ViewGroup.LayoutParams.WRAP_CONTENT
+        )
+
+        textView.width = TypedValue.applyDimension(
+            TypedValue.COMPLEX_UNIT_DIP,
+            160f,
+            activity.resources.displayMetrics
+        ).roundToInt()
+
+        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSize)
+        linearLayout.addView(textView)
+        return linearLayout
+    }
+}
diff --git a/ui/settings.gradle b/ui/settings.gradle
index 95fe210..71c7318 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -64,6 +64,7 @@
 if (startParameter.projectProperties.containsKey('compose.desktop')) {
     includeProject(":ui:ui-desktop", "ui-desktop")
     includeProject(":ui:ui-desktop:android-emu", "ui-desktop/android-emu")
+    includeProject(":ui:ui-desktop:samples", "ui-desktop/samples")
 }
 includeProject(":ui:ui-foundation", "ui-foundation")
 includeProject(":ui:ui-foundation:integration-tests:ui-foundation-demos", "ui-foundation/integration-tests/foundation-demos")
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropAndroidInCompose.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropAndroidInCompose.kt
index 4229802..cdaae2a 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropAndroidInCompose.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropAndroidInCompose.kt
@@ -37,7 +37,7 @@
 import androidx.ui.layout.preferredHeight
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.viewinterop.AndroidView
 
@@ -90,7 +90,7 @@
 private fun AndroidTapInComposeTap() {
     var theView: View? = null
 
-    val onTap: (PxPosition) -> Unit = {
+    val onTap: (Offset) -> Unit = {
         theView?.setBackgroundColor(Color.BLUE)
     }
 
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropComposeInAndroid.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropComposeInAndroid.kt
index 272f6ca..8532fcd 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropComposeInAndroid.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/PointerInputInteropComposeInAndroid.kt
@@ -34,6 +34,7 @@
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.HorizontalScroller
 import androidx.ui.foundation.VerticalScroller
+import androidx.ui.foundation.clickable
 import androidx.ui.foundation.drawBackground
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.RectangleShape
@@ -47,7 +48,6 @@
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.preferredWidth
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.material.ripple.ripple
 import androidx.ui.unit.dp
 
 val ComposeInAndroidDemos = DemoCategory(
@@ -198,20 +198,16 @@
 
             val currentColor = state { Color.LightGray }
 
-            val tap =
-                Modifier.tapGestureFilter {
-                    currentColor.value =
-                        if (currentColor.value == Color.Blue) Color.Yellow else Color.Blue
-                }
-
             Box(
                 Modifier
                     .drawBackground(Color.Gray, RectangleShape)
                     .fillMaxWidth()
                     .preferredHeight(456.dp)
                     .wrapContentSize()
-                    .ripple()
-                    .plus(tap)
+                    .clickable {
+                        currentColor.value =
+                            if (currentColor.value == Color.Blue) Color.Yellow else Color.Blue
+                    }
                     .drawBackground(currentColor.value, RectangleShape)
                     .preferredSize(192.dp)
             )
diff --git a/ui/ui-animation-core/api/0.1.0-dev14.txt b/ui/ui-animation-core/api/0.1.0-dev14.txt
index 3944e4a..714fd9c 100644
--- a/ui/ui-animation-core/api/0.1.0-dev14.txt
+++ b/ui/ui-animation-core/api/0.1.0-dev14.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,6 +280,14 @@
     property public final Integer? iterations;
   }
 
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
+    ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
+    method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
+    method public androidx.animation.TransitionDefinition<T> getDef();
+    method public long getDuration();
+    property public final long duration;
+  }
+
   public final class SnapBuilder<T> extends androidx.animation.AnimationBuilder<T> {
     ctor public SnapBuilder();
     method public <V extends androidx.animation.AnimationVector> androidx.animation.Animation<V> build$lintWithKotlin(androidx.animation.TwoWayConverter<T,V> converter);
@@ -295,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -310,6 +325,8 @@
   }
 
   public final class ToolingGlueKt {
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -326,6 +343,13 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+    ctor public TransitionAnimation.TransitionAnimationClockObserver();
+    method public androidx.animation.TransitionAnimation<T> getAnimation();
+    method public void onAnimationFrame(long frameTimeMillis);
+    property public final androidx.animation.TransitionAnimation<T> animation;
+  }
+
   public final class TransitionAnimationKt {
   }
 
diff --git a/ui/ui-animation-core/api/current.txt b/ui/ui-animation-core/api/current.txt
index 3944e4a..714fd9c 100644
--- a/ui/ui-animation-core/api/current.txt
+++ b/ui/ui-animation-core/api/current.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,6 +280,14 @@
     property public final Integer? iterations;
   }
 
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
+    ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
+    method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
+    method public androidx.animation.TransitionDefinition<T> getDef();
+    method public long getDuration();
+    property public final long duration;
+  }
+
   public final class SnapBuilder<T> extends androidx.animation.AnimationBuilder<T> {
     ctor public SnapBuilder();
     method public <V extends androidx.animation.AnimationVector> androidx.animation.Animation<V> build$lintWithKotlin(androidx.animation.TwoWayConverter<T,V> converter);
@@ -295,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -310,6 +325,8 @@
   }
 
   public final class ToolingGlueKt {
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -326,6 +343,13 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+    ctor public TransitionAnimation.TransitionAnimationClockObserver();
+    method public androidx.animation.TransitionAnimation<T> getAnimation();
+    method public void onAnimationFrame(long frameTimeMillis);
+    property public final androidx.animation.TransitionAnimation<T> animation;
+  }
+
   public final class TransitionAnimationKt {
   }
 
diff --git a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev14.txt
index b3720d5..714fd9c 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev14.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,7 +280,7 @@
     property public final Integer? iterations;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class SeekableAnimation<T> {
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
     ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
     method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
     method public androidx.animation.TransitionDefinition<T> getDef();
@@ -303,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -318,8 +325,8 @@
   }
 
   public final class ToolingGlueKt {
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -336,7 +343,7 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
     ctor public TransitionAnimation.TransitionAnimationClockObserver();
     method public androidx.animation.TransitionAnimation<T> getAnimation();
     method public void onAnimationFrame(long frameTimeMillis);
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 b3720d5..714fd9c 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_current.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,7 +280,7 @@
     property public final Integer? iterations;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class SeekableAnimation<T> {
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
     ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
     method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
     method public androidx.animation.TransitionDefinition<T> getDef();
@@ -303,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -318,8 +325,8 @@
   }
 
   public final class ToolingGlueKt {
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -336,7 +343,7 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
     ctor public TransitionAnimation.TransitionAnimationClockObserver();
     method public androidx.animation.TransitionAnimation<T> getAnimation();
     method public void onAnimationFrame(long frameTimeMillis);
diff --git a/ui/ui-animation-core/api/restricted_0.1.0-dev14.txt b/ui/ui-animation-core/api/restricted_0.1.0-dev14.txt
index b3720d5..714fd9c 100644
--- a/ui/ui-animation-core/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-animation-core/api/restricted_0.1.0-dev14.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,7 +280,7 @@
     property public final Integer? iterations;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class SeekableAnimation<T> {
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
     ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
     method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
     method public androidx.animation.TransitionDefinition<T> getDef();
@@ -303,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -318,8 +325,8 @@
   }
 
   public final class ToolingGlueKt {
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -336,7 +343,7 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
     ctor public TransitionAnimation.TransitionAnimationClockObserver();
     method public androidx.animation.TransitionAnimation<T> getAnimation();
     method public void onAnimationFrame(long frameTimeMillis);
diff --git a/ui/ui-animation-core/api/restricted_current.txt b/ui/ui-animation-core/api/restricted_current.txt
index b3720d5..714fd9c 100644
--- a/ui/ui-animation-core/api/restricted_current.txt
+++ b/ui/ui-animation-core/api/restricted_current.txt
@@ -138,7 +138,8 @@
     property public abstract T! value;
   }
 
-  public abstract sealed class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+  public abstract class BaseAnimationClock implements androidx.animation.AnimationClockObservable {
+    ctor public BaseAnimationClock();
     method public void subscribe(androidx.animation.AnimationClockObserver observer);
     method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
     field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
@@ -188,7 +189,7 @@
   }
 
   public final class ExponentialDecay implements androidx.animation.DecayAnimation {
-    ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
+    ctor public ExponentialDecay(@FloatRange(from=null, to=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, to=null, fromInclusive=null) float absVelocityThreshold);
     ctor public ExponentialDecay();
     method public float getAbsVelocityThreshold();
     method public long getDurationMillis(float start, float startVelocity);
@@ -212,6 +213,9 @@
     property public androidx.animation.TwoWayConverter<java.lang.Integer,androidx.animation.AnimationVector1D> typeConverter;
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalAnimationApi {
+  }
+
   public enum InterruptionHandling {
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
@@ -276,7 +280,7 @@
     property public final Integer? iterations;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class SeekableAnimation<T> {
+  @androidx.animation.InternalAnimationApi public final class SeekableAnimation<T> {
     ctor public SeekableAnimation(androidx.animation.TransitionDefinition<T> def, T! fromState, T! toState);
     method public java.util.Map<androidx.animation.PropKey<java.lang.Object,androidx.animation.AnimationVector>,java.lang.Object> getAnimValuesAt(long playTime);
     method public androidx.animation.TransitionDefinition<T> getDef();
@@ -303,6 +307,9 @@
   }
 
   public final class SpringEstimationKt {
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(float stiffness, float dampingRatio, float initialVelocity, float initialDisplacement, float delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double stiffness, double dampingRatio, double initialVelocity, double initialDisplacement, double delta);
+    method @VisibleForTesting(otherwise=3) public static long estimateAnimationDurationMillis(double springConstant, double dampingCoefficient, double mass, double initialVelocity, double initialDisplacement, double delta);
   }
 
   public final class SpringSimulationKt {
@@ -318,8 +325,8 @@
   }
 
   public final class ToolingGlueKt {
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
+    method @androidx.animation.InternalAnimationApi public static <T> androidx.animation.SeekableAnimation<T> createSeekableAnimation(androidx.animation.TransitionAnimation<T>, T? fromState, T? toState);
+    method @androidx.animation.InternalAnimationApi public static <T> java.util.Set<T> getStates(androidx.animation.TransitionAnimation<T>);
   }
 
   public final class TransitionAnimation<T> implements androidx.animation.TransitionState {
@@ -336,7 +343,7 @@
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onUpdate;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
+  @androidx.animation.InternalAnimationApi public final class TransitionAnimation.TransitionAnimationClockObserver implements androidx.animation.AnimationClockObserver {
     ctor public TransitionAnimation.TransitionAnimationClockObserver();
     method public androidx.animation.TransitionAnimation<T> getAnimation();
     method public void onAnimationFrame(long frameTimeMillis);
diff --git a/ui/ui-animation-core/build.gradle b/ui/ui-animation-core/build.gradle
index 439d4cd..0222e9a 100644
--- a/ui/ui-animation-core/build.gradle
+++ b/ui/ui-animation-core/build.gradle
@@ -25,25 +25,39 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXUiPlugin")
-    id("org.jetbrains.kotlin.android")
-    id("kotlin-android-extensions")
+    id("kotlin-multiplatform")
 }
 
 dependencies {
-    implementation(KOTLIN_STDLIB)
+    kotlinPlugin project(path: ":compose:compose-compiler")
+}
 
-    api "androidx.annotation:annotation:1.1.0"
-    implementation project(":ui:ui-util")
+kotlin {
+    android()
+    sourceSets {
+        commonMain.dependencies {
+            implementation project(":ui:ui-util")
+            implementation (KOTLIN_STDLIB_COMMON)
+        }
+        androidMain.dependencies {
+            api "androidx.annotation:annotation:1.1.0"
+            implementation (KOTLIN_STDLIB)
+        }
 
-    testImplementation(ANDROIDX_TEST_RULES)
-    testImplementation(ANDROIDX_TEST_RUNNER)
-    testImplementation(JUNIT)
-    testImplementation(TRUTH)
-    testImplementation(KOTLIN_COROUTINES_CORE)
+        androidTest.dependencies {
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(JUNIT)
+            implementation(TRUTH)
+            implementation(KOTLIN_COROUTINES_CORE)
+        }
 
-    androidTestImplementation(ANDROIDX_TEST_RULES)
-    androidTestImplementation(ANDROIDX_TEST_RUNNER)
-    androidTestImplementation(JUNIT)
+        androidAndroidTest.dependencies {
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(JUNIT)
+        }
+    }
 }
 
 androidx {
@@ -57,6 +71,8 @@
 
 tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
-        freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental"]
+        freeCompilerArgs += [
+            "-Xuse-experimental=kotlin.Experimental"
+        ]
     }
 }
diff --git a/ui/ui-animation-core/src/main/AndroidManifest.xml b/ui/ui-animation-core/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-animation-core/src/main/AndroidManifest.xml
rename to ui/ui-animation-core/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-animation-core/src/androidMain/kotlin/androidx/animation/AndroidAnimationClock.kt b/ui/ui-animation-core/src/androidMain/kotlin/androidx/animation/AndroidAnimationClock.kt
new file mode 100644
index 0000000..5360e90
--- /dev/null
+++ b/ui/ui-animation-core/src/androidMain/kotlin/androidx/animation/AndroidAnimationClock.kt
@@ -0,0 +1,85 @@
+// ktlint-disable filename
+/*
+ * 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.animation
+
+import android.os.Handler
+import android.os.Looper
+import android.view.Choreographer
+import java.util.concurrent.CountDownLatch
+
+/**
+ * Default Choreographer based clock that pushes a new frame to all subscribers on each
+ * Choreographer tick, until all subscribers have unsubscribed. An instance of this clock will be
+ * provided through [AnimationClockAmbient][androidx.ui.core.AnimationClockAmbient] at the root
+ * of the composition tree.
+ *
+ * If initialized from any other thread but the main thread, part of the initialization is done
+ * synchronously on the main thread. If this poses a problem, consider initializing this clock on
+ * the main thread itself.
+ */
+actual class DefaultAnimationClock actual constructor() : BaseAnimationClock() {
+
+    private val mainChoreographer: Choreographer
+
+    init {
+        /**
+         * If not initializing on the main thread, a message will be posted on the main thread to
+         * fetch the Choreographer, and initialization blocks until that fetch is completed.
+         */
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            mainChoreographer = Choreographer.getInstance()
+        } else {
+            val latch = CountDownLatch(1)
+            var choreographer: Choreographer? = null
+            Handler(Looper.getMainLooper()).postAtFrontOfQueue {
+                try {
+                    choreographer = Choreographer.getInstance()
+                } finally {
+                    latch.countDown()
+                }
+            }
+            latch.await()
+            mainChoreographer = choreographer!!
+        }
+    }
+
+    @Volatile
+    private var subscribedToChoreographer = false
+
+    private val frameCallback = Choreographer.FrameCallback {
+        dispatchTime(it / 1000000)
+    }
+
+    override fun subscribe(observer: AnimationClockObserver) {
+        if (!subscribedToChoreographer) {
+            mainChoreographer.postFrameCallback(frameCallback)
+            subscribedToChoreographer = true
+        }
+        super.subscribe(observer)
+    }
+
+    override fun dispatchTime(frameTimeMillis: Long) {
+        super.dispatchTime(frameTimeMillis)
+        subscribedToChoreographer = if (hasObservers()) {
+            mainChoreographer.postFrameCallback(frameCallback)
+            true
+        } else {
+            false
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimatedValue.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimatedValue.kt
similarity index 93%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimatedValue.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimatedValue.kt
index 871d162..e1e0b0b 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/AnimatedValue.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimatedValue.kt
@@ -16,7 +16,6 @@
 
 package androidx.animation
 
-import android.util.Log
 import androidx.animation.AnimationEndReason.BoundReached
 import androidx.animation.AnimationEndReason.Interrupted
 import androidx.animation.AnimationEndReason.TargetReached
@@ -107,11 +106,12 @@
     // end of the animation.
     private var lastFrameTime: Long = Unset
 
-    private var animationClockObserver = object : AnimationClockObserver {
-        override fun onAnimationFrame(frameTimeMillis: Long) {
-            doAnimationFrame(frameTimeMillis)
+    private var animationClockObserver: AnimationClockObserver =
+        object : AnimationClockObserver {
+            override fun onAnimationFrame(frameTimeMillis: Long) {
+                doAnimationFrame(frameTimeMillis)
+            }
         }
-    }
 
     private fun defaultPhysicsBuilder(): PhysicsBuilder<T> {
         return visibilityThreshold?.let {
@@ -146,12 +146,6 @@
             value, velocityVector, targetValue, anim.build(typeConverter), typeConverter
         )
 
-        if (DEBUG) {
-            Log.w(
-                "AnimValue", "To value called: start value: $value," +
-                        "end value: $targetValue, velocity: $velocityVector"
-            )
-        }
         this.onEnd = onEnd
         startAnimation(animationWrapper)
     }
@@ -202,13 +196,6 @@
 
     protected open fun checkFinished(playtime: Long) {
         val animationFinished = anim.isFinished(playtime)
-        if (DEBUG) {
-            val debugLogMessage = if (animationFinished)
-                "value = $value, playtime = $playtime, animation finished"
-            else
-                "value = $value, playtime = $playtime, velocity: $velocityVector"
-            Log.w("AnimValue", debugLogMessage)
-        }
         if (animationFinished) endAnimation()
     }
 
@@ -229,9 +216,6 @@
             isRunning = true
             clock.subscribe(animationClockObserver)
         }
-        if (DEBUG) {
-            Log.w("AnimValue", "start animation")
-        }
     }
 
     internal fun endAnimation(endReason: AnimationEndReason = TargetReached) {
@@ -239,9 +223,6 @@
         isRunning = false
         startTime = Unset
         lastFrameTime = Unset
-        if (DEBUG) {
-            Log.w("AnimValue", "end animation with reason $endReason")
-        }
         notifyEnded(endReason, value)
         // reset velocity after notifyFinish as we might need to return it in onFinished callback
         // depending on whether or not velocity was involved in the animation
@@ -412,17 +393,8 @@
     }
 
     // start from current value with the given velocity
-    if (DEBUG) {
-        Log.w("AnimFloat", "Calculating target. Value: $value, velocity: $startVelocity")
-    }
     targetValue = decay.getTarget(value, startVelocity)
     val targetAnimation = adjustTarget(targetValue)
-    if (DEBUG) {
-        Log.w(
-            "AnimFloat", "original targetValue: $targetValue, new target:" +
-                    " ${targetAnimation?.target}"
-        )
-    }
     if (targetAnimation == null) {
         val animWrapper = DecayAnimationWrapper(value, startVelocity, decay)
         startAnimation(animWrapper)
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationBuilder.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationBuilder.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationClock.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationClock.kt
similarity index 68%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimationClock.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationClock.kt
index 161f342..511dc89 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationClock.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationClock.kt
@@ -16,83 +16,17 @@
 
 package androidx.animation
 
-import android.os.Handler
-import android.os.Looper
-import android.view.Choreographer
-import androidx.annotation.CallSuper
-import androidx.annotation.RestrictTo
-import org.jetbrains.annotations.TestOnly
-import java.util.concurrent.CountDownLatch
+import androidx.ui.util.annotation.CallSuper
+
+expect class DefaultAnimationClock() : BaseAnimationClock
 
 /** @suppress */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@InternalAnimationApi
 var rootAnimationClockFactory: () -> AnimationClockObservable = { DefaultAnimationClock() }
-    @TestOnly
+    // @TestOnly
     set
 
 /**
- * Default Choreographer based clock that pushes a new frame to all subscribers on each
- * Choreographer tick, until all subscribers have unsubscribed. An instance of this clock will be
- * provided through [AnimationClockAmbient][androidx.ui.core.AnimationClockAmbient] at the root
- * of the composition tree.
- *
- * If initialized from any other thread but the main thread, part of the initialization is done
- * synchronously on the main thread. If this poses a problem, consider initializing this clock on
- * the main thread itself.
- */
-class DefaultAnimationClock : BaseAnimationClock() {
-
-    private val mainChoreographer: Choreographer
-
-    init {
-        /**
-         * If not initializing on the main thread, a message will be posted on the main thread to
-         * fetch the Choreographer, and initialization blocks until that fetch is completed.
-         */
-        if (Looper.myLooper() == Looper.getMainLooper()) {
-            mainChoreographer = Choreographer.getInstance()
-        } else {
-            val latch = CountDownLatch(1)
-            var choreographer: Choreographer? = null
-            Handler(Looper.getMainLooper()).postAtFrontOfQueue {
-                try {
-                    choreographer = Choreographer.getInstance()
-                } finally {
-                    latch.countDown()
-                }
-            }
-            latch.await()
-            mainChoreographer = choreographer!!
-        }
-    }
-
-    @Volatile
-    private var subscribedToChoreographer = false
-
-    private val frameCallback = Choreographer.FrameCallback {
-        dispatchTime(it / 1000000)
-    }
-
-    override fun subscribe(observer: AnimationClockObserver) {
-        if (!subscribedToChoreographer) {
-            mainChoreographer.postFrameCallback(frameCallback)
-            subscribedToChoreographer = true
-        }
-        super.subscribe(observer)
-    }
-
-    override fun dispatchTime(frameTimeMillis: Long) {
-        super.dispatchTime(frameTimeMillis)
-        subscribedToChoreographer = if (hasObservers()) {
-            mainChoreographer.postFrameCallback(frameCallback)
-            true
-        } else {
-            false
-        }
-    }
-}
-
-/**
  * A custom clock whose frame time can be manually updated via mutating [clockTimeMillis].
  * Observers will be called immediately with the current time when they are subscribed. Use
  * [dispatchOnSubscribe] = false to wait for the next tick instead, which can be useful if the
@@ -132,7 +66,7 @@
  * Base implementation for the AnimationClockObservable that handles the subscribing and
  * unsubscribing logic that would be common for all custom animation clocks.
  */
-sealed class BaseAnimationClock : AnimationClockObservable {
+abstract class BaseAnimationClock : AnimationClockObservable {
     // Using LinkedHashSet to increase removal performance
     private val observers: MutableSet<AnimationClockObserver> = LinkedHashSet()
 
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationClockObservable.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationClockObservable.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimationClockObservable.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationClockObservable.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationVectors.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationVectors.kt
similarity index 96%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimationVectors.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationVectors.kt
index 91af2ac..cb19d52 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationVectors.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationVectors.kt
@@ -16,6 +16,8 @@
 
 package androidx.animation
 
+import androidx.ui.util.identityHashCode
+
 /**
  * [AnimationVector] class that is the base class of [AnimationVector1D], [AnimationVector2D],
  * [AnimationVector3D] and [AnimationVector4D]. In order to animate any arbitrary type, it is
@@ -120,7 +122,7 @@
     override fun equals(other: Any?): Boolean =
         other is AnimationVector1D && other.value == value
 
-    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun hashCode(): Int = identityHashCode()
 }
 
 /**
@@ -172,7 +174,7 @@
     override fun equals(other: Any?): Boolean =
         other is AnimationVector2D && other.v1 == v1 && other.v2 == v2
 
-    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun hashCode(): Int = identityHashCode()
 }
 
 /**
@@ -235,7 +237,7 @@
     override fun equals(other: Any?): Boolean =
         other is AnimationVector3D && other.v1 == v1 && other.v2 == v2 && other.v3 == v3
 
-    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun hashCode(): Int = identityHashCode()
 }
 
 /**
@@ -310,5 +312,5 @@
                 other.v3 == v3 &&
                 other.v4 == v4
 
-    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun hashCode(): Int = identityHashCode()
 }
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationWrapper.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationWrapper.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/AnimationWrapper.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/AnimationWrapper.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/ComplexDouble.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ComplexDouble.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/ComplexDouble.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ComplexDouble.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/DecayAnimation.kt
similarity index 89%
rename from ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/DecayAnimation.kt
index 652288c..749cdfd 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/DecayAnimation.kt
@@ -16,7 +16,7 @@
 
 package androidx.animation
 
-import androidx.annotation.FloatRange
+import androidx.ui.util.annotation.FloatRange
 import kotlin.math.abs
 import kotlin.math.exp
 import kotlin.math.ln
@@ -89,8 +89,18 @@
  * the animation will travel with the same starting condition.
  */
 class ExponentialDecay(
-    @FloatRange(from = 0.0, fromInclusive = false) frictionMultiplier: Float = 1f,
-    @FloatRange(from = 0.0, fromInclusive = false) absVelocityThreshold: Float = 0.1f
+    @FloatRange(
+        from = 0.0,
+        // TODO(b/158069385): use POSITIVE_INFINITY constant once it's possible to do in MPP code.
+        to = 3.4e38, // POSITIVE_INFINITY,
+        fromInclusive = false
+    ) frictionMultiplier: Float = 1f,
+    @FloatRange(
+        from = 0.0,
+        // TODO(b/158069385): use POSITIVE_INFINITY constant once it's possible to do in MPP code.
+        to = 3.4e38, // POSITIVE_INFINITY,
+        fromInclusive = false
+    ) absVelocityThreshold: Float = 0.1f
 ) : DecayAnimation {
 
     override val absVelocityThreshold: Float = max(0.0000001f, abs(absVelocityThreshold))
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/DynamicTargetAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/DynamicTargetAnimation.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/DynamicTargetAnimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/DynamicTargetAnimation.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/Easing.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/Easing.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/Easing.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/Easing.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/FloatAnimation.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/FloatAnimation.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/PropKey.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/PropKey.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/PropKey.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/PropKey.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringEstimation.kt
similarity index 97%
rename from ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringEstimation.kt
index 2126129..99846cd 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringEstimation.kt
@@ -16,7 +16,8 @@
 
 package androidx.animation
 
-import androidx.annotation.VisibleForTesting
+import androidx.ui.util.annotation.VisibleForTesting
+
 import kotlin.math.abs
 import kotlin.math.exp
 import kotlin.math.ln
@@ -26,7 +27,7 @@
 /**
  * Returns the estimated time that the spring will last be at [delta]
  */
-@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+@VisibleForTesting(otherwise = 3 /* VisibleForTesting.PACKAGE_PRIVATE */)
 fun estimateAnimationDurationMillis(
     stiffness: Float,
     dampingRatio: Float,
@@ -44,7 +45,7 @@
 /**
  * Returns the estimated time that the spring will last be at [delta]
  */
-@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+@VisibleForTesting(otherwise = 3 /* VisibleForTesting.PACKAGE_PRIVATE */)
 fun estimateAnimationDurationMillis(
     stiffness: Double,
     dampingRatio: Double,
@@ -67,7 +68,7 @@
 /**
  * Returns the estimated time that the spring will last be at [delta]
  */
-@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+@VisibleForTesting(otherwise = 3 /* VisibleForTesting.PACKAGE_PRIVATE */)
 fun estimateAnimationDurationMillis(
     springConstant: Double,
     dampingCoefficient: Double,
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/SpringSimulation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringSimulation.kt
similarity index 81%
rename from ui/ui-animation-core/src/main/java/androidx/animation/SpringSimulation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringSimulation.kt
index 39a927e..76845c4 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/SpringSimulation.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/SpringSimulation.kt
@@ -20,6 +20,11 @@
 import androidx.ui.util.unpackFloat1
 import androidx.ui.util.unpackFloat2
 
+import kotlin.math.cos
+import kotlin.math.exp
+import kotlin.math.sin
+import kotlin.math.sqrt
+
 /**
  * Spring Simulation simulates spring physics, and allows you to query the motion (i.e. value and
  * velocity) at certain time in the future based on the starting velocity and value.
@@ -58,7 +63,7 @@
 internal class SpringSimulation(var finalPosition: Float) {
 
     // Natural frequency
-    private var naturalFreq = Math.sqrt(Spring.StiffnessVeryLow.toDouble())
+    private var naturalFreq = sqrt(Spring.StiffnessVeryLow.toDouble())
 
     // Indicates whether the spring has been initialized
     private var initialized = false
@@ -76,7 +81,7 @@
             if (stiffness <= 0) {
                 throw IllegalArgumentException("Spring stiffness constant must be positive.")
             }
-            naturalFreq = Math.sqrt(value.toDouble())
+            naturalFreq = sqrt(value.toDouble())
             // All the intermediate values need to be recalculated.
             initialized = false
         }
@@ -131,12 +136,12 @@
         if (dampingRatio > 1) {
             // Over damping
             gammaPlus =
-                (-dampingRatio * naturalFreq + naturalFreq * Math.sqrt(dampingRatioSquared - 1))
+                (-dampingRatio * naturalFreq + naturalFreq * sqrt(dampingRatioSquared - 1))
             gammaMinus =
-                (-dampingRatio * naturalFreq - naturalFreq * Math.sqrt(dampingRatioSquared - 1))
+                (-dampingRatio * naturalFreq - naturalFreq * sqrt(dampingRatioSquared - 1))
         } else if (dampingRatio >= 0 && dampingRatio < 1) {
             // Under damping
-            dampedFreq = naturalFreq * Math.sqrt(1 - dampingRatioSquared)
+            dampedFreq = naturalFreq * sqrt(1 - dampingRatioSquared)
         }
 
         initialized = true
@@ -161,31 +166,31 @@
                     (gammaMinus - gammaPlus)))
             val coeffB = ((gammaMinus * adjustedDisplacement - lastVelocity) /
                     (gammaMinus - gammaPlus))
-            displacement = (coeffA * Math.pow(Math.E, gammaMinus * deltaT) +
-                    coeffB * Math.pow(Math.E, gammaPlus * deltaT))
-            currentVelocity = (coeffA * gammaMinus * Math.pow(Math.E, gammaMinus * deltaT) +
-                    coeffB * gammaPlus * Math.pow(Math.E, gammaPlus * deltaT))
+            displacement = (coeffA * exp(gammaMinus * deltaT) +
+                    coeffB * exp(gammaPlus * deltaT))
+            currentVelocity = (coeffA * gammaMinus * exp(gammaMinus * deltaT) +
+                    coeffB * gammaPlus * exp(gammaPlus * deltaT))
         } else if (dampingRatio == 1.0f) {
             // Critically damped
             val coeffA = adjustedDisplacement
             val coeffB = lastVelocity + naturalFreq * adjustedDisplacement
-            displacement = (coeffA + coeffB * deltaT) * Math.pow(Math.E, -naturalFreq * deltaT)
+            displacement = (coeffA + coeffB * deltaT) * exp(-naturalFreq * deltaT)
             currentVelocity =
-                    (((coeffA + coeffB * deltaT) * Math.pow(Math.E, -naturalFreq * deltaT) *
-                    (-naturalFreq)) + coeffB * Math.pow(Math.E, -naturalFreq * deltaT))
+                    (((coeffA + coeffB * deltaT) * exp(-naturalFreq * deltaT) *
+                    (-naturalFreq)) + coeffB * exp(-naturalFreq * deltaT))
         } else {
             // Underdamped
             val cosCoeff = adjustedDisplacement
             val sinCoeff =
                 ((1 / dampedFreq) * (((dampingRatio * naturalFreq * adjustedDisplacement) +
                     lastVelocity)))
-            displacement = (Math.pow(Math.E, -dampingRatio * naturalFreq * deltaT) *
-                    ((cosCoeff * Math.cos(dampedFreq * deltaT) +
-                            sinCoeff * Math.sin(dampedFreq * deltaT))))
-            currentVelocity = (displacement * (-naturalFreq) * dampingRatio + (Math.pow(Math.E,
-                    - dampingRatio * naturalFreq * deltaT) * ((-dampedFreq * cosCoeff *
-                    Math.sin(dampedFreq * deltaT) + dampedFreq * sinCoeff *
-                    Math.cos(dampedFreq * deltaT)))))
+            displacement = (exp(-dampingRatio * naturalFreq * deltaT) *
+                    ((cosCoeff * cos(dampedFreq * deltaT) +
+                            sinCoeff * sin(dampedFreq * deltaT))))
+            currentVelocity = (displacement * (-naturalFreq) * dampingRatio + (exp(
+                    -dampingRatio * naturalFreq * deltaT) * ((-dampedFreq * cosCoeff *
+                    sin(dampedFreq * deltaT) + dampedFreq * sinCoeff *
+                    cos(dampedFreq * deltaT)))))
         }
 
         val newValue = (displacement + finalPosition).toFloat()
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/ToolingGlue.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
similarity index 87%
rename from ui/ui-animation-core/src/main/java/androidx/animation/ToolingGlue.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
index acc5e99..f522ba4 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/ToolingGlue.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/ToolingGlue.kt
@@ -16,7 +16,9 @@
 
 package androidx.animation
 
-import androidx.annotation.RestrictTo
+@RequiresOptIn(message = "This API is internal to library.")
+@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
+annotation class InternalAnimationApi
 
 /**
  * Seekable animation class provides utilities to create an animation using a state pair, and
@@ -24,9 +26,9 @@
  * entirely stateless in terms of animation lifecycle. This design makes it easy for higher level
  * stateful construct to be built on top of it.
  *
- * This API is intended for tools' use only. Hence the @RestrictTo.
+ * This API is intended for tools' use only. Hence the @InternalAnimationApi.
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@InternalAnimationApi
 class SeekableAnimation<T>(
     val def: TransitionDefinition<T>,
     fromState: T,
@@ -81,19 +83,19 @@
  * Creates a [SeekableAnimation] using the same [TransitionDefinition] that the
  * [TransitionAnimation] is created from.
  *
- * Note: This API is intended for tools' use only. Hence the @RestrictTo.
+ * Note: This API is intended for tools' use only. Hence the @InternalAnimationApi.
  *
  * @param fromState The state that a [SeekableAnimation] will start from.
  * @param toState The state that a [SeekableAnimation] will end in.
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@InternalAnimationApi
 fun <T> TransitionAnimation<T>.createSeekableAnimation(fromState: T, toState: T) =
     SeekableAnimation<T>(def, fromState, toState)
 
 /**
  * Returns the all states available in a [TransitionDefinition].
  *
- * This API is intended for tools' use only. Hence the @RestrictTo.
+ * This API is intended for tools' use only. Hence the @InternalAnimationApi.
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@InternalAnimationApi
 fun <T> TransitionAnimation<T>.getStates(): Set<T> = def.states.keys
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
similarity index 96%
rename from ui/ui-animation-core/src/main/java/androidx/animation/TransitionAnimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
index f5e94c7..5d34294 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionAnimation.kt
+++ b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionAnimation.kt
@@ -16,9 +16,7 @@
 
 package androidx.animation
 
-import android.util.Log
 import androidx.animation.InterruptionHandling.UNINTERRUPTIBLE
-import androidx.annotation.RestrictTo
 
 /**
  * [TransitionAnimation] is the underlying animation used in [androidx.ui.animation.Transition] for
@@ -40,6 +38,7 @@
  *
  * @see [androidx.ui.animation.Transition]
  */
+@OptIn(InternalAnimationApi::class)
 class TransitionAnimation<T>(
     internal val def: TransitionDefinition<T>,
     private val clock: AnimationClockObservable,
@@ -71,10 +70,9 @@
     private var startVelocityMap: MutableMap<PropKey<Any, AnimationVector>, Any> = mutableMapOf()
 
     // Named class for animation clock observer to help with tools' reflection.
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @InternalAnimationApi
     inner class TransitionAnimationClockObserver : AnimationClockObserver {
-        // This API is intended for tools' use only. Hence the @RestrictTo.
-        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        // This API is intended for tools' use only. Hence the @InternalAnimationApi.
         val animation: TransitionAnimation<T> = this@TransitionAnimation
         override fun onAnimationFrame(frameTimeMillis: Long) {
             doAnimationFrame(frameTimeMillis)
@@ -128,9 +126,6 @@
 
         fromState = AnimationState(currentState, toState.name)
         toState = newState
-        if (DEBUG) {
-            Log.w("TransAnim", "Animating to new state: ${toState.name}")
-        }
 
         // Start animation should be called after all the setup has been done
         startAnimation()
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionDefinition.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionDefinition.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionState.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionState.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/TransitionState.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/TransitionState.kt
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt b/ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/VectorAnimation.kt
similarity index 100%
rename from ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
rename to ui/ui-animation-core/src/commonMain/kotlin/androidx/animation/VectorAnimation.kt
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/ToolingGlueTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/ToolingGlueTest.kt
index 4b65ff6..d8c5010 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/ToolingGlueTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/ToolingGlueTest.kt
@@ -24,6 +24,7 @@
 import java.lang.Long.max
 
 @RunWith(JUnit4::class)
+@OptIn(InternalAnimationApi::class)
 class ToolingGlueTest {
     @Test
     fun testSeekableAnimation() {
diff --git a/ui/ui-animation/api/0.1.0-dev14.txt b/ui/ui-animation/api/0.1.0-dev14.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/0.1.0-dev14.txt
+++ b/ui/ui-animation/api/0.1.0-dev14.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/api/current.txt b/ui/ui-animation/api/current.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/current.txt
+++ b/ui/ui-animation/api/current.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-animation/api/public_plus_experimental_0.1.0-dev14.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-animation/api/public_plus_experimental_0.1.0-dev14.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/api/public_plus_experimental_current.txt b/ui/ui-animation/api/public_plus_experimental_current.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation/api/public_plus_experimental_current.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/api/restricted_0.1.0-dev14.txt b/ui/ui-animation/api/restricted_0.1.0-dev14.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-animation/api/restricted_0.1.0-dev14.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/api/restricted_current.txt b/ui/ui-animation/api/restricted_current.txt
index 2eaf1a9..cca0e95 100644
--- a/ui/ui-animation/api/restricted_current.txt
+++ b/ui/ui-animation/api/restricted_current.txt
@@ -64,19 +64,19 @@
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.IntPx,androidx.animation.AnimationVector1D> getIntPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.Position,androidx.animation.AnimationVector2D> getPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxBounds,androidx.animation.AnimationVector4D> getPxBoundsToVectorConverter();
-    method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
+    method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getPxPositionToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.unit.PxSize,androidx.animation.AnimationVector2D> getPxSizeToVectorConverter();
     method public static androidx.animation.TwoWayConverter<java.lang.Float,androidx.animation.AnimationVector1D> getPxToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Rect,androidx.animation.AnimationVector4D> getRectToVectorConverter();
     method public static androidx.animation.TwoWayConverter<androidx.ui.geometry.Size,androidx.animation.AnimationVector2D> getSizeToVectorConverter();
   }
 
-  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> {
+  public final class PxPositionPropKey implements androidx.animation.PropKey<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> {
     ctor public PxPositionPropKey(String label);
     ctor public PxPositionPropKey();
     method public String getLabel();
-    method public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> getTypeConverter();
-    property public androidx.animation.TwoWayConverter<androidx.ui.unit.PxPosition,androidx.animation.AnimationVector2D> typeConverter;
+    method public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> getTypeConverter();
+    property public androidx.animation.TwoWayConverter<androidx.ui.geometry.Offset,androidx.animation.AnimationVector2D> typeConverter;
   }
 
   public final class PxPropKey implements androidx.animation.PropKey<java.lang.Float,androidx.animation.AnimationVector1D> {
@@ -108,9 +108,9 @@
     method @androidx.compose.Composable public static androidx.ui.unit.PxSize animate(androidx.ui.unit.PxSize target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxSize> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxSize,kotlin.Unit>? endListener = null);
-    method @androidx.compose.Composable public static androidx.ui.unit.PxPosition animate(androidx.ui.unit.PxPosition target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxPosition> animBuilder = remember({ 
+    method @androidx.compose.Composable public static androidx.ui.geometry.Offset animate(androidx.ui.geometry.Offset target, androidx.animation.AnimationBuilder<androidx.ui.geometry.Offset> animBuilder = remember({ 
     return <init>()
-}), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? endListener = null);
+}), kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? endListener = null);
     method @androidx.compose.Composable public static androidx.ui.unit.PxBounds animate(androidx.ui.unit.PxBounds target, androidx.animation.AnimationBuilder<androidx.ui.unit.PxBounds> animBuilder = remember({ 
     return <init>()
 }), kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxBounds,kotlin.Unit>? endListener = null);
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/AnimatableSeekBarDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/AnimatableSeekBarDemo.kt
index 3adf558..38879ec 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/AnimatableSeekBarDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/AnimatableSeekBarDemo.kt
@@ -42,7 +42,6 @@
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredHeight
 import androidx.ui.layout.preferredSize
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import androidx.ui.unit.sp
 
@@ -98,13 +97,13 @@
     val animValue = animatedFloat(0f)
 
     val dragObserver = object : DragObserver {
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             animValue.snapTo(animValue.targetValue + dragDistance.x)
             return dragDistance
         }
     }
 
-    val onPress: (PxPosition) -> Unit = { position ->
+    val onPress: (Offset) -> Unit = { position ->
         animValue.animateTo(position.x,
             TweenBuilder<Float>().apply {
                 duration = 400
@@ -127,7 +126,7 @@
         clock.clockTimeMillis = (400 * (x / size.width)).toLong().coerceIn(0, 399)
         // draw bar
         val barHeight = 10.0f
-        val offset = Offset(0.0f, center.dy - 5)
+        val offset = Offset(0.0f, center.y - 5)
         drawRect(
             Color.Gray,
             topLeft = offset,
@@ -142,7 +141,7 @@
         // draw ticker
         drawCircle(
             Color.Magenta,
-            center = Offset(xConstraint, center.dy),
+            center = Offset(xConstraint, center.y),
             radius = 40f
         )
     }
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/FancyScrollingDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/FancyScrollingDemo.kt
index 5d4356d..aba57ba 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/FancyScrollingDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/FancyScrollingDemo.kt
@@ -37,7 +37,6 @@
 import androidx.ui.layout.fillMaxWidth
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredHeight
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import androidx.ui.unit.sp
 import kotlin.math.roundToInt
@@ -53,13 +52,13 @@
         val animScroll = animatedFloat(0f)
         val itemWidth = state { 0f }
         val gesture = Modifier.rawDragGestureFilter(dragObserver = object : DragObserver {
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 // Snap to new drag position
                 animScroll.snapTo(animScroll.value + dragDistance.x)
                 return dragDistance
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
 
                 // Uses default decay animation to calculate where the fling will settle,
                 // and adjust that position as needed. The target animation will be used for
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/GestureBasedAnimationDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/GestureBasedAnimationDemo.kt
index 17872f7..9926cfb 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/GestureBasedAnimationDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/GestureBasedAnimationDemo.kt
@@ -75,7 +75,7 @@
     Canvas(modifier.fillMaxSize()) {
         drawRect(
             color,
-            topLeft = Offset(center.dx - halfSize * scale, center.dy - halfSize * scale),
+            topLeft = Offset(center.x - halfSize * scale, center.y - halfSize * scale),
             size = Size(halfSize * 2 * scale, halfSize * 2 * scale)
         )
     }
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SpringBackScrollingDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SpringBackScrollingDemo.kt
index 128778a..f5cd62d 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SpringBackScrollingDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SpringBackScrollingDemo.kt
@@ -37,7 +37,6 @@
 import androidx.ui.layout.fillMaxWidth
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredHeight
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import androidx.ui.unit.sp
 import kotlin.math.roundToInt
@@ -54,12 +53,12 @@
         val itemWidth = state { 0f }
         val isFlinging = state { false }
         val gesture = Modifier.rawDragGestureFilter(dragObserver = object : DragObserver {
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 animScroll.snapTo(animScroll.targetValue + dragDistance.x)
                 return dragDistance
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 isFlinging.value = true
                 animScroll.fling(velocity.x, onEnd = { _, _, _ ->
                     isFlinging.value = false
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateAnimationWithInterruptionsDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateAnimationWithInterruptionsDemo.kt
index cc0cdce..41bb9a6 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateAnimationWithInterruptionsDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateAnimationWithInterruptionsDemo.kt
@@ -22,7 +22,9 @@
 import androidx.animation.TransitionState
 import androidx.animation.transitionDefinition
 import androidx.compose.Composable
-import androidx.compose.Recompose
+import androidx.compose.getValue
+import androidx.compose.mutableStateOf
+import androidx.compose.setValue
 import androidx.ui.animation.ColorPropKey
 import androidx.ui.animation.Transition
 import androidx.ui.core.Modifier
@@ -74,21 +76,18 @@
 
 @Composable
 private fun ColorRect() {
-    var toState = OverlayState.Closed
-    Recompose { recompose ->
-        handler.postDelayed(object : Runnable {
-            override fun run() {
-                if ((0..1).random() == 0) {
-                    toState = OverlayState.Open
-                } else {
-                    toState = OverlayState.Closed
-                }
-                recompose()
+    var toState by mutableStateOf(OverlayState.Closed)
+    handler.postDelayed(object : Runnable {
+        override fun run() {
+            if ((0..1).random() == 0) {
+                toState = OverlayState.Open
+            } else {
+                toState = OverlayState.Closed
             }
-        }, (200..800).random().toLong())
-        Transition(definition = definition, toState = toState) { state ->
-            ColorRectState(state = state)
         }
+    }, (200..800).random().toLong())
+    Transition(definition = definition, toState = toState) { state ->
+        ColorRectState(state = state)
     }
 }
 
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateBasedRippleDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateBasedRippleDemo.kt
index 800f557..e0c3b41 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateBasedRippleDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/StateBasedRippleDemo.kt
@@ -34,7 +34,6 @@
 import androidx.ui.geometry.Offset
 import androidx.ui.graphics.Color
 import androidx.ui.layout.fillMaxSize
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 
 @Composable
@@ -49,7 +48,7 @@
     val radius = with(DensityAmbient.current) { TargetRadius.toPx() }
     val toState = state { ButtonStatus.Initial }
     val rippleTransDef = remember { createTransDef(radius) }
-    val onPress: (PxPosition) -> Unit = { position ->
+    val onPress: (Offset) -> Unit = { position ->
         down.x = position.x
         down.y = position.y
         toState.value = ButtonStatus.Pressed
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismissDemo.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismissDemo.kt
index 91df541..ac5cb2ff 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismissDemo.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismissDemo.kt
@@ -40,7 +40,6 @@
 import androidx.ui.layout.fillMaxWidth
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredHeight
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import androidx.ui.unit.sp
 import kotlin.math.sign
@@ -68,7 +67,7 @@
     val itemWidth = state { 0f }
     val isFlinging = state { false }
     val modifier = Modifier.rawDragGestureFilter(dragObserver = object : DragObserver {
-        override fun onStart(downPosition: PxPosition) {
+        override fun onStart(downPosition: Offset) {
             itemBottom.setBounds(0f, height)
             if (isFlinging.value && itemBottom.targetValue < 100f) {
                 reset()
@@ -83,7 +82,7 @@
             }
         }
 
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             itemBottom.snapTo(itemBottom.targetValue + dragDistance.y)
             return dragDistance
         }
@@ -105,7 +104,7 @@
             }
         }
 
-        override fun onStop(velocity: PxPosition) {
+        override fun onStop(velocity: Offset) {
             isFlinging.value = true
             itemBottom.fling(velocity.y,
                 ExponentialDecay(3.0f),
@@ -143,11 +142,11 @@
     height: Float,
     index: Int
 ) {
-    val offset = Offset(center.dx - width * 1.5f + horizontalOffset + padding, size.height - height)
+    val offset = Offset(center.x - width * 1.5f + horizontalOffset + padding, size.height - height)
     val rectSize = Size(width - (2 * padding), height)
     drawRect(colors[index % colors.size], offset, rectSize)
 
-    if (offset.dx >= 0) {
+    if (offset.x >= 0) {
         // draw another item
         drawRect(
             colors[(index - 1 + colors.size) % colors.size],
@@ -165,7 +164,7 @@
     alpha: Float
 ) = drawRect(
         colors[index % colors.size],
-        topLeft = Offset(center.dx - width / 2 + padding, bottom - height),
+        topLeft = Offset(center.x - width / 2 + padding, bottom - height),
         size = Size(width - (2 * padding), height),
         alpha = alpha
     )
diff --git a/ui/ui-animation/src/androidTest/java/androidx/ui/animation/SingleValueAnimationTest.kt b/ui/ui-animation/src/androidTest/java/androidx/ui/animation/SingleValueAnimationTest.kt
index 43a1252..a5b20e0 100644
--- a/ui/ui-animation/src/androidTest/java/androidx/ui/animation/SingleValueAnimationTest.kt
+++ b/ui/ui-animation/src/androidTest/java/androidx/ui/animation/SingleValueAnimationTest.kt
@@ -40,7 +40,7 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.Position
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.dp
 import androidx.ui.util.lerp
@@ -148,7 +148,7 @@
                     PxPositionToVectorConverter.convertFromVector(endVal)
                 else
                     PxPositionToVectorConverter.convertFromVector(startVal),
-                TweenBuilder<PxPosition>().apply(animConfig)
+                TweenBuilder<Offset>().apply(animConfig)
             )
 
             pxSizeValue = animate(
diff --git a/ui/ui-animation/src/main/java/androidx/ui/animation/PropertyKeys.kt b/ui/ui-animation/src/main/java/androidx/ui/animation/PropertyKeys.kt
index ab47f19..d0da9e3 100644
--- a/ui/ui-animation/src/main/java/androidx/ui/animation/PropertyKeys.kt
+++ b/ui/ui-animation/src/main/java/androidx/ui/animation/PropertyKeys.kt
@@ -34,11 +34,10 @@
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.Position
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
 import kotlin.math.roundToInt
 
 /**
@@ -60,13 +59,13 @@
 }
 
 /**
- * Built-in property key for [PxPosition] properties.
+ * Built-in property key for [Offset] properties.
  *
  * @param label Label for distinguishing different prop keys in Android Studio.
  */
 class PxPositionPropKey(
     override val label: String = "PxPositionPropKey"
-) : PropKey<PxPosition, AnimationVector2D> {
+) : PropKey<Offset, AnimationVector2D> {
     override val typeConverter = PxPositionToVectorConverter
 }
 
@@ -178,12 +177,12 @@
 )
 
 /**
- * A type converter that converts a [PxPosition] to a [AnimationVector2D], and vice versa.
+ * A type converter that converts a [Offset] to a [AnimationVector2D], and vice versa.
  */
-val PxPositionToVectorConverter: TwoWayConverter<PxPosition, AnimationVector2D> =
+val PxPositionToVectorConverter: TwoWayConverter<Offset, AnimationVector2D> =
     TwoWayConverter(
         convertToVector = { AnimationVector2D(it.x, it.y) },
-        convertFromVector = { PxPosition(it.v1, it.v2) }
+        convertFromVector = { Offset(it.v1, it.v2) }
     )
 
 /**
@@ -192,7 +191,7 @@
 val PxSizeToVectorConverter: TwoWayConverter<PxSize, AnimationVector2D> =
     TwoWayConverter(
         convertToVector = { AnimationVector2D(it.width, it.height) },
-        convertFromVector = { PxSize(it.v1.px, it.v2.px) }
+        convertFromVector = { PxSize(it.v1, it.v2) }
     )
 
 /**
diff --git a/ui/ui-animation/src/main/java/androidx/ui/animation/SingleValueAnimation.kt b/ui/ui-animation/src/main/java/androidx/ui/animation/SingleValueAnimation.kt
index daece9f..3667491 100644
--- a/ui/ui-animation/src/main/java/androidx/ui/animation/SingleValueAnimation.kt
+++ b/ui/ui-animation/src/main/java/androidx/ui/animation/SingleValueAnimation.kt
@@ -38,7 +38,7 @@
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.Position
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 
 private const val DpVisibilityThreshold = 0.1f
@@ -294,15 +294,15 @@
 }
 
 /**
- * Fire-and-forget animation [Composable] for [PxPosition]. Once such an animation is created, it
+ * Fire-and-forget animation [Composable] for [Offset]. Once such an animation is created, it
  * will be positionally memoized, like other @[Composable]s. To trigger the animation, or alter the
  * course of the animation, simply supply a different [target] to the [Composable].
  *
  * Note, [animate] is for simple animations that cannot be canceled. For cancellable animations
  * see [animatedValue].
  *
- *    val position : PxPosition = animate(
- *        if (selected) PxPosition(0.px, 0.px) else PxPosition(20.px, 20.px))
+ *    val position : Offset = animate(
+ *        if (selected) Offset(0.px, 0.px) else Offset(20.px, 20.px))
  *
  * @param target Target value of the animation
  * @param animBuilder The animation that will be used to change the value through time. Physics
@@ -311,10 +311,10 @@
  */
 @Composable
 fun animate(
-    target: PxPosition,
-    animBuilder: AnimationBuilder<PxPosition> = remember { PhysicsBuilder() },
-    endListener: ((PxPosition) -> Unit)? = null
-): PxPosition {
+    target: Offset,
+    animBuilder: AnimationBuilder<Offset> = remember { PhysicsBuilder() },
+    endListener: ((Offset) -> Unit)? = null
+): Offset {
     return animate(
         target, PxPositionToVectorConverter, animBuilder, PxVisibilityThreshold2D, endListener)
 }
diff --git a/ui/ui-animation/src/test/java/androidx/ui/animation/ConverterTest.kt b/ui/ui-animation/src/test/java/androidx/ui/animation/ConverterTest.kt
index 4853a3a..05e03eb 100644
--- a/ui/ui-animation/src/test/java/androidx/ui/animation/ConverterTest.kt
+++ b/ui/ui-animation/src/test/java/androidx/ui/animation/ConverterTest.kt
@@ -22,7 +22,7 @@
 import androidx.ui.geometry.Rect
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.colorspace.ColorSpaces
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import junit.framework.TestCase.assertEquals
 import org.junit.Test
@@ -72,9 +72,9 @@
     fun testPxPositionConverter() {
         val x = Random.nextFloat()
         val y = Random.nextFloat()
-        assertEquals(PxPosition(x, y),
+        assertEquals(Offset(x, y),
             PxPositionToVectorConverter.convertFromVector(AnimationVector2D(x, y)))
         assertEquals(AnimationVector2D(x, y),
-            PxPositionToVectorConverter.convertToVector(PxPosition(x, y)))
+            PxPositionToVectorConverter.convertToVector(Offset(x, y)))
     }
 }
\ No newline at end of file
diff --git a/ui/ui-core/api/0.1.0-dev14.txt b/ui/ui-core/api/0.1.0-dev14.txt
index 617c8ce..1db61ff 100644
--- a/ui/ui-core/api/0.1.0-dev14.txt
+++ b/ui/ui-core/api/0.1.0-dev14.txt
@@ -227,13 +227,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -371,15 +371,15 @@
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -390,9 +390,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -417,37 +417,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -457,45 +449,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -549,13 +540,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -653,6 +647,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -693,14 +688,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -709,9 +706,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -749,14 +746,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -770,8 +767,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -932,7 +929,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -941,9 +938,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -960,18 +957,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -979,7 +976,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1012,7 +1009,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1048,7 +1045,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1734,9 +1731,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1838,7 +1835,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1850,7 +1847,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/api/api_lint.ignore b/ui/ui-core/api/api_lint.ignore
index 90fe967..1ea2e0b 100644
--- a/ui/ui-core/api/api_lint.ignore
+++ b/ui/ui-core/api/api_lint.ignore
@@ -29,6 +29,20 @@
     Context is distinct, so it must be the first argument (method `subcomposeInto`)
 
 
+MissingNullability: androidx.ui.core.Measured#constructor-impl(androidx.ui.core.Placeable):
+    Missing nullability on method `constructor-impl` return
+MissingNullability: androidx.ui.core.Measured#equals-impl(androidx.ui.core.Placeable, Object) parameter #0:
+    Missing nullability on parameter `p` in method `equals-impl`
+MissingNullability: androidx.ui.core.Measured#getHeight-impl(androidx.ui.core.Placeable) parameter #0:
+    Missing nullability on parameter `$this` in method `getHeight-impl`
+MissingNullability: androidx.ui.core.Measured#getWidth-impl(androidx.ui.core.Placeable) parameter #0:
+    Missing nullability on parameter `$this` in method `getWidth-impl`
+MissingNullability: androidx.ui.core.Measured#hashCode-impl(androidx.ui.core.Placeable) parameter #0:
+    Missing nullability on parameter `p` in method `hashCode-impl`
+MissingNullability: androidx.ui.core.Measured#toString-impl(androidx.ui.core.Placeable):
+    Missing nullability on method `toString-impl` return
+MissingNullability: androidx.ui.core.Measured#toString-impl(androidx.ui.core.Placeable) parameter #0:
+    Missing nullability on parameter `p` in method `toString-impl`
 MissingNullability: androidx.ui.core.PointerId#toString-impl(long):
     Missing nullability on method `toString-impl` return
 MissingNullability: androidx.ui.core.TransformOrigin#toString-impl(long):
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 617c8ce..1db61ff 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -227,13 +227,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -371,15 +371,15 @@
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -390,9 +390,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -417,37 +417,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -457,45 +449,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -549,13 +540,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -653,6 +647,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -693,14 +688,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -709,9 +706,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -749,14 +746,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -770,8 +767,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -932,7 +929,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -941,9 +938,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -960,18 +957,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -979,7 +976,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1012,7 +1009,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1048,7 +1045,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1734,9 +1731,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1838,7 +1835,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1850,7 +1847,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev14.txt
index 1fa269f..b42c265 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev14.txt
@@ -227,13 +227,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -372,15 +372,15 @@
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -391,9 +391,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -418,37 +418,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -458,45 +450,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -550,13 +541,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -654,6 +648,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -695,14 +690,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -711,9 +708,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -751,14 +748,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -772,8 +769,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -934,7 +931,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -943,9 +940,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -962,18 +959,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -981,7 +978,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1014,7 +1011,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1050,7 +1047,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1736,9 +1733,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1840,7 +1837,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1852,7 +1849,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 1fa269f..b42c265 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -227,13 +227,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -372,15 +372,15 @@
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -391,9 +391,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -418,37 +418,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -458,45 +450,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -550,13 +541,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -654,6 +648,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -695,14 +690,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -711,9 +708,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -751,14 +748,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -772,8 +769,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -934,7 +931,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -943,9 +940,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -962,18 +959,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -981,7 +978,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1014,7 +1011,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1050,7 +1047,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1736,9 +1733,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1840,7 +1837,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1852,7 +1849,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/api/restricted_0.1.0-dev14.txt b/ui/ui-core/api/restricted_0.1.0-dev14.txt
index e266052..f005cd5 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev14.txt
@@ -233,13 +233,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -407,7 +407,6 @@
     method public androidx.ui.core.LayoutDirection getLayoutDirection();
     method @androidx.compose.Stable public float toDp(float);
     method @androidx.compose.Stable public float toDp(int);
-    method @androidx.compose.Stable public float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public float toDp-gshw56o(int);
     method @androidx.compose.Stable public float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public int toIntPx-ipo6vVg(float);
@@ -417,22 +416,21 @@
     method @androidx.compose.Stable public androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public long toSp(float);
     method @androidx.compose.Stable public long toSp(int);
-    method @androidx.compose.Stable public long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public long toSp-gshw56o(int);
     method @androidx.compose.Stable public long toSp-ipo6vVg(float);
   }
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -443,9 +441,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -470,37 +468,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -510,45 +500,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -602,13 +591,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -708,6 +700,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -749,14 +742,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -765,9 +760,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -805,14 +800,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -826,8 +821,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -988,7 +983,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -997,9 +992,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -1016,18 +1011,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -1035,7 +1030,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1068,7 +1063,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1104,7 +1099,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1790,9 +1785,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1894,7 +1889,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1906,7 +1901,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index e266052..f005cd5 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -233,13 +233,13 @@
   }
 
   @androidx.compose.Immutable public final class ConsumedData {
-    ctor public ConsumedData(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    ctor public ConsumedData(androidx.ui.geometry.Offset positionChange, boolean downChange);
     ctor public ConsumedData();
-    method public androidx.ui.unit.PxPosition component1();
+    method public androidx.ui.geometry.Offset component1();
     method public boolean component2();
-    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.unit.PxPosition positionChange, boolean downChange);
+    method @androidx.compose.Immutable public androidx.ui.core.ConsumedData copy(androidx.ui.geometry.Offset positionChange, boolean downChange);
     method public boolean getDownChange();
-    method public androidx.ui.unit.PxPosition getPositionChange();
+    method public androidx.ui.geometry.Offset getPositionChange();
   }
 
   public abstract class ContentDrawScope extends androidx.ui.graphics.drawscope.DrawScope {
@@ -407,7 +407,6 @@
     method public androidx.ui.core.LayoutDirection getLayoutDirection();
     method @androidx.compose.Stable public float toDp(float);
     method @androidx.compose.Stable public float toDp(int);
-    method @androidx.compose.Stable public float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public float toDp-gshw56o(int);
     method @androidx.compose.Stable public float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public int toIntPx-ipo6vVg(float);
@@ -417,22 +416,21 @@
     method @androidx.compose.Stable public androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public long toSp(float);
     method @androidx.compose.Stable public long toSp(int);
-    method @androidx.compose.Stable public long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public long toSp-gshw56o(int);
     method @androidx.compose.Stable public long toSp-ipo6vVg(float);
   }
 
   public interface LayoutCoordinates {
     method public androidx.ui.unit.PxBounds childBoundingBox(androidx.ui.core.LayoutCoordinates child);
-    method public androidx.ui.unit.PxPosition childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.unit.PxPosition childLocal);
+    method public androidx.ui.geometry.Offset childToLocal(androidx.ui.core.LayoutCoordinates child, androidx.ui.geometry.Offset childLocal);
     method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.core.LayoutCoordinates? getParentCoordinates();
     method public java.util.Set<androidx.ui.core.AlignmentLine> getProvidedAlignmentLines();
     method public androidx.ui.unit.IntPxSize getSize();
-    method public androidx.ui.unit.PxPosition globalToLocal(androidx.ui.unit.PxPosition global);
+    method public androidx.ui.geometry.Offset globalToLocal(androidx.ui.geometry.Offset global);
     method public boolean isAttached();
-    method public androidx.ui.unit.PxPosition localToGlobal(androidx.ui.unit.PxPosition local);
-    method public androidx.ui.unit.PxPosition localToRoot(androidx.ui.unit.PxPosition local);
+    method public androidx.ui.geometry.Offset localToGlobal(androidx.ui.geometry.Offset local);
+    method public androidx.ui.geometry.Offset localToRoot(androidx.ui.geometry.Offset local);
     property public abstract boolean isAttached;
     property public abstract androidx.ui.core.LayoutCoordinates? parentCoordinates;
     property public abstract java.util.Set<androidx.ui.core.AlignmentLine> providedAlignmentLines;
@@ -443,9 +441,9 @@
     method public static androidx.ui.unit.PxBounds getBoundsInParent(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getBoundsInRoot(androidx.ui.core.LayoutCoordinates);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getGlobalPosition(androidx.ui.core.LayoutCoordinates);
-    method public static androidx.ui.unit.PxPosition getPositionInParent(androidx.ui.core.LayoutCoordinates);
-    method public static inline androidx.ui.unit.PxPosition getPositionInRoot(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getGlobalPosition(androidx.ui.core.LayoutCoordinates);
+    method public static androidx.ui.geometry.Offset getPositionInParent(androidx.ui.core.LayoutCoordinates);
+    method public static inline androidx.ui.geometry.Offset getPositionInRoot(androidx.ui.core.LayoutCoordinates);
   }
 
   public final class LayoutKt {
@@ -470,37 +468,29 @@
     method public void attach(androidx.ui.core.Owner owner);
     method public void detach();
     method public void draw(androidx.ui.graphics.Canvas canvas);
-    method public boolean getAffectsParentSize();
     method public androidx.ui.unit.IntPx? getAlignmentLine(androidx.ui.core.AlignmentLine line);
     method @Deprecated public boolean getCanMultiMeasure();
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
-    method public androidx.ui.core.Constraints getConstraints();
     method public androidx.ui.core.LayoutCoordinates getCoordinates();
     method public int getDepth();
     method @Deprecated public boolean getHandlesParentData();
     method public int getHeight();
-    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
     method public androidx.ui.core.MeasureScope getMeasureScope();
     method public androidx.ui.core.Modifier getModifier();
     method public java.util.List<androidx.ui.core.ModifierInfo> getModifierInfo();
-    method public boolean getNeedsRelayout();
-    method public boolean getNeedsRemeasure();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnAttach();
     method public kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? getOnDetach();
     method public androidx.ui.core.Owner? getOwner();
     method public androidx.ui.core.LayoutNode? getParent();
     method public Object? getParentData();
-    method public boolean getPositionedDuringMeasurePass();
     method public androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? getRef();
     method public int getWidth();
-    method public boolean hitTest(androidx.ui.unit.PxPosition pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
+    method public boolean hitTest(androidx.ui.geometry.Offset pointerPositionRelativeToScreen, java.util.List<androidx.ui.core.pointerinput.PointerInputFilter> hitPointerInputFilters);
     method public void ignoreModelReads(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public void insertAt(int index, androidx.ui.core.LayoutNode instance);
-    method public boolean isLayingOut();
-    method public boolean isMeasuring();
     method public boolean isPlaced();
-    method public void layout();
     method public int maxIntrinsicHeight-Ujlv2dA(int width, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-Ujlv2dA(int height, androidx.ui.core.LayoutDirection layoutDirection);
     method public androidx.ui.core.Placeable measure(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection);
@@ -510,45 +500,44 @@
     method public void onInvalidate();
     method public void place-rRMsBxU(int x, int y);
     method public void removeAt(int index, int count);
+    method public void requestRelayout();
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
-    method public void setConstraints(androidx.ui.core.Constraints p);
     method public void setDepth(int p);
     method @Deprecated public void setHandlesParentData(boolean p);
-    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
     method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
     method public void setModifier(androidx.ui.core.Modifier value);
     method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
     method public void setOnDetach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
-    method public void setPositionedDuringMeasurePass(boolean p);
     method public void setRef(androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? value);
-    property public final boolean affectsParentSize;
     property @Deprecated public final boolean canMultiMeasure;
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
-    property public final androidx.ui.core.Constraints constraints;
     property public final androidx.ui.core.LayoutCoordinates coordinates;
     property public final int depth;
     property @Deprecated public final boolean handlesParentData;
     property public final int height;
-    property public final boolean isLayingOut;
-    property public final boolean isMeasuring;
     property public final boolean isPlaced;
-    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
     property public final androidx.ui.core.LayoutNode.MeasureBlocks measureBlocks;
     property public final androidx.ui.core.MeasureScope measureScope;
     property public final androidx.ui.core.Modifier modifier;
-    property public final boolean needsRelayout;
-    property public final boolean needsRemeasure;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onAttach;
     property public final kotlin.jvm.functions.Function1<androidx.ui.core.Owner,kotlin.Unit>? onDetach;
     property public final androidx.ui.core.Owner? owner;
     property public final androidx.ui.core.LayoutNode? parent;
     property public Object? parentData;
-    property public final boolean positionedDuringMeasurePass;
     property public final androidx.ui.core.Ref<androidx.ui.core.LayoutNode>? ref;
     property public final int width;
   }
 
+  public enum LayoutNode.LayoutState {
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRemeasure;
+    enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Ready;
+  }
+
   public static interface LayoutNode.MeasureBlocks {
     method public int maxIntrinsicHeight-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int w, androidx.ui.core.LayoutDirection layoutDirection);
     method public int maxIntrinsicWidth-5Bu9FwI(androidx.ui.core.IntrinsicMeasureScope intrinsicMeasureScope, java.util.List<? extends androidx.ui.core.IntrinsicMeasurable> measurables, int h, androidx.ui.core.LayoutDirection layoutDirection);
@@ -602,13 +591,16 @@
   public final class MeasureScopeKt {
   }
 
-  public final class Measured {
-    ctor public Measured(internal androidx.ui.core.Placeable placeable);
-    method public operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine alignmentLine);
-    method public int getHeight();
-    method public int getWidth();
-    property public final int height;
-    property public final int width;
+  public final inline class Measured {
+    ctor public Measured();
+    method public static androidx.ui.core.Placeable! constructor-impl(internal androidx.ui.core.Placeable placeable);
+    method public static inline boolean equals-impl(androidx.ui.core.Placeable! p, Object? p1);
+    method public static boolean equals-impl0(androidx.ui.core.Placeable p1, androidx.ui.core.Placeable p2);
+    method public static operator androidx.ui.unit.IntPx? get-impl(androidx.ui.core.Placeable $this, androidx.ui.core.AlignmentLine alignmentLine);
+    method public static int getHeight-impl(androidx.ui.core.Placeable! $this);
+    method public static int getWidth-impl(androidx.ui.core.Placeable! $this);
+    method public static inline int hashCode-impl(androidx.ui.core.Placeable! p);
+    method public static inline String! toString-impl(androidx.ui.core.Placeable! p);
   }
 
   public final class ModelObserver {
@@ -708,6 +700,7 @@
     method public void onDetach(androidx.ui.core.LayoutNode node);
     method public void onInvalidate(androidx.ui.core.LayoutNode layoutNode);
     method public void onRequestMeasure(androidx.ui.core.LayoutNode layoutNode);
+    method public void onRequestRelayout(androidx.ui.core.LayoutNode layoutNode);
     method public void onSemanticsChange();
     method public void pauseModelReadObserveration(kotlin.jvm.functions.Function0<kotlin.Unit> block);
     method public boolean requestFocus();
@@ -749,14 +742,16 @@
     method public abstract operator androidx.ui.unit.IntPx? get(androidx.ui.core.AlignmentLine line);
     method protected final androidx.ui.unit.IntPxPosition getApparentToRealOffset();
     method public final int getHeight();
-    method protected abstract androidx.ui.unit.IntPxSize getMeasuredSize();
-    method protected abstract androidx.ui.core.Constraints getMeasurementConstraints();
+    method protected final androidx.ui.unit.IntPxSize getMeasuredSize();
+    method protected final androidx.ui.core.Constraints getMeasurementConstraints();
     method public final int getWidth();
     method protected abstract void place(androidx.ui.unit.IntPxPosition position);
+    method protected final void setMeasuredSize(androidx.ui.unit.IntPxSize value);
+    method protected final void setMeasurementConstraints(androidx.ui.core.Constraints p);
     property protected final androidx.ui.unit.IntPxPosition apparentToRealOffset;
     property public final int height;
-    property protected abstract androidx.ui.unit.IntPxSize measuredSize;
-    property protected abstract androidx.ui.core.Constraints measurementConstraints;
+    property protected final androidx.ui.unit.IntPxSize measuredSize;
+    property protected final androidx.ui.core.Constraints measurementConstraints;
     property public final int width;
   }
 
@@ -765,9 +760,9 @@
     method public abstract androidx.ui.core.LayoutDirection getParentLayoutDirection();
     method public abstract int getParentWidth();
     method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
-    method public final void place(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void place(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void place-sXe7h04(androidx.ui.core.Placeable, int x, int y);
-    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.PxPosition position);
+    method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.geometry.Offset position);
     method public final void placeAbsolute(androidx.ui.core.Placeable, androidx.ui.unit.IntPxPosition position);
     method public final void placeAbsolute-sXe7h04(androidx.ui.core.Placeable, int x, int y);
     property public abstract androidx.ui.core.LayoutDirection parentLayoutDirection;
@@ -805,14 +800,14 @@
   }
 
   @androidx.compose.Immutable public final class PointerInputData {
-    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    ctor public PointerInputData(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     ctor public PointerInputData();
     method public androidx.ui.unit.Uptime? component1();
-    method public androidx.ui.unit.PxPosition? component2();
+    method public androidx.ui.geometry.Offset? component2();
     method public boolean component3();
-    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.unit.PxPosition? position, boolean down);
+    method @androidx.compose.Immutable public androidx.ui.core.PointerInputData copy(androidx.ui.unit.Uptime? uptime, androidx.ui.geometry.Offset? position, boolean down);
     method public boolean getDown();
-    method public androidx.ui.unit.PxPosition? getPosition();
+    method public androidx.ui.geometry.Offset? getPosition();
     method public androidx.ui.unit.Uptime? getUptime();
   }
 
@@ -826,8 +821,8 @@
     method public static androidx.ui.core.PointerInputChange consumeAllChanges(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumeDownChange(androidx.ui.core.PointerInputChange);
     method public static androidx.ui.core.PointerInputChange consumePositionChange(androidx.ui.core.PointerInputChange, float consumedDx, float consumedDy);
-    method public static androidx.ui.unit.PxPosition positionChange(androidx.ui.core.PointerInputChange);
-    method public static androidx.ui.unit.PxPosition positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChange(androidx.ui.core.PointerInputChange);
+    method public static androidx.ui.geometry.Offset positionChangeIgnoreConsumed(androidx.ui.core.PointerInputChange);
     method public static boolean positionChanged(androidx.ui.core.PointerInputChange);
     method public static boolean positionChangedIgnoreConsumed(androidx.ui.core.PointerInputChange);
   }
@@ -988,7 +983,7 @@
   }
 
   public final class DoubleTapGestureFilterKt {
-    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDoubleTap);
+    method public static androidx.ui.core.Modifier doubleTapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDoubleTap);
   }
 
   public final class DragGestureFilterKt {
@@ -997,9 +992,9 @@
 
   public interface DragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
-    method public default void onStart(androidx.ui.unit.PxPosition downPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class DragSlopExceededGestureFilterKt {
@@ -1016,18 +1011,18 @@
 
   public interface LongPressDragObserver {
     method public default void onCancel();
-    method public default androidx.ui.unit.PxPosition onDrag(androidx.ui.unit.PxPosition dragDistance);
+    method public default androidx.ui.geometry.Offset onDrag(androidx.ui.geometry.Offset dragDistance);
     method public default void onDragStart();
-    method public default void onLongPress(androidx.ui.unit.PxPosition pxPosition);
-    method public default void onStop(androidx.ui.unit.PxPosition velocity);
+    method public default void onLongPress(androidx.ui.geometry.Offset pxPosition);
+    method public default void onStop(androidx.ui.geometry.Offset velocity);
   }
 
   public final class LongPressGestureFilterKt {
-    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onLongPress);
+    method public static androidx.ui.core.Modifier longPressGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onLongPress);
   }
 
   public final class PressIndicatorGestureFilterKt {
-    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
+    method public static androidx.ui.core.Modifier pressIndicatorGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit>? onStart = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onStop = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel = null, boolean enabled = true);
   }
 
   public final class RawDragGestureFilterKt {
@@ -1035,7 +1030,7 @@
   }
 
   public final class RawPressStartGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
+    method public static androidx.ui.core.Modifier rawPressStartGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onPressStart, boolean enabled = false, androidx.ui.core.PointerEventPass executionPass = androidx.ui.core.PointerEventPass.PostUp);
   }
 
   public final class RawScaleGestureFilterKt {
@@ -1068,7 +1063,7 @@
   }
 
   public final class TapGestureFilterKt {
-    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onTap);
+    method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
 
 }
@@ -1104,7 +1099,7 @@
 
   public final class VelocityTracker {
     ctor public VelocityTracker();
-    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.unit.PxPosition position);
+    method public void addPosition(androidx.ui.unit.Uptime uptime, androidx.ui.geometry.Offset position);
     method public androidx.ui.unit.Velocity calculateVelocity();
     method public void resetTracking();
   }
@@ -1790,9 +1785,9 @@
 
   public interface Selectable {
     method public androidx.ui.geometry.Rect getBoundingBox(int offset);
-    method public androidx.ui.unit.PxPosition getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
+    method public androidx.ui.geometry.Offset getHandlePosition(androidx.ui.core.selection.Selection selection, boolean isStartHandle);
     method public androidx.ui.core.LayoutCoordinates? getLayoutCoordinates();
-    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.PxPosition endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
+    method public androidx.ui.core.selection.Selection? getSelection(androidx.ui.geometry.Offset startPosition, androidx.ui.geometry.Offset endPosition, androidx.ui.core.LayoutCoordinates containerLayoutCoordinates, boolean longPress, androidx.ui.core.selection.Selection? previousSelection = null, boolean isStartHandle = true);
     method public androidx.ui.text.AnnotatedString getText();
   }
 
@@ -1894,7 +1889,7 @@
     method public androidx.ui.core.LayoutNode getComponentNode();
     method public androidx.ui.core.semantics.SemanticsConfiguration getConfig();
     method public androidx.ui.unit.PxBounds getGlobalBounds();
-    method public androidx.ui.unit.PxPosition getGlobalPosition();
+    method public androidx.ui.geometry.Offset getGlobalPosition();
     method public boolean getHasChildren();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsNode? getParent();
@@ -1906,7 +1901,7 @@
     property public final java.util.List<androidx.ui.core.semantics.SemanticsNode> children;
     property public final androidx.ui.core.semantics.SemanticsConfiguration config;
     property public final androidx.ui.unit.PxBounds globalBounds;
-    property public final androidx.ui.unit.PxPosition globalPosition;
+    property public final androidx.ui.geometry.Offset globalPosition;
     property public final boolean hasChildren;
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
diff --git a/ui/ui-core/build.gradle b/ui/ui-core/build.gradle
index 38b0ca7..c073121 100644
--- a/ui/ui-core/build.gradle
+++ b/ui/ui-core/build.gradle
@@ -86,7 +86,10 @@
 
 tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
-        freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental", "-XXLanguage:+InlineClasses"]
+        freeCompilerArgs += [
+            "-Xuse-experimental=kotlin.Experimental",
+            "-XXLanguage:+InlineClasses"
+        ]
         useIR = true
     }
 }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
index bba3ab4..10556e1 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
@@ -36,7 +36,7 @@
 import androidx.ui.layout.preferredHeight
 import androidx.ui.material.MaterialTheme
 import androidx.ui.foundation.TextFieldValue
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 @Composable
@@ -111,7 +111,7 @@
     }
 }
 
-private fun LayoutCoordinates.boundingBox() = localToGlobal(PxPosition.Origin).run {
+private fun LayoutCoordinates.boundingBox() = localToGlobal(Offset.Zero).run {
     Rect(
         x.toInt(),
         y.toInt(),
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapGestureDetectorDemo.kt
index 4fd73d9..623fd08 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapGestureDetectorDemo.kt
@@ -28,7 +28,7 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -38,7 +38,7 @@
 fun DoubleTapGestureFilterDemo() {
     val color = state { Colors.random() }
 
-    val onDoubleTap: (PxPosition) -> Unit = {
+    val onDoubleTap: (Offset) -> Unit = {
         color.value = color.value.anotherRandomColor()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapInTapDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapInTapDemo.kt
index e6186c3..df425fac 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapInTapDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DoubleTapInTapDemo.kt
@@ -29,7 +29,7 @@
 import androidx.ui.layout.Column
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.padding
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 @Composable
@@ -39,11 +39,11 @@
     val innerColor = state { defaultColor }
     val outerColor = state { defaultColor }
 
-    val onTap: (PxPosition) -> Unit = {
+    val onTap: (Offset) -> Unit = {
         outerColor.value = outerColor.value.next()
     }
 
-    val onDoubleTap: (PxPosition) -> Unit = { _ ->
+    val onDoubleTap: (Offset) -> Unit = { _ ->
         innerColor.value = innerColor.value.prev()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
index 64abcb8..6294fe0 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
@@ -33,7 +33,7 @@
 import androidx.ui.layout.offset
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -43,7 +43,7 @@
 @Composable
 fun DragAndScaleGestureDetectorDemo() {
     val size = state { 200.dp }
-    val offset = state { PxPosition.Origin }
+    val offset = state { Offset.Zero }
     val dragInScale = state { false }
 
     val scaleObserver = object : ScaleObserver {
@@ -53,13 +53,13 @@
     }
 
     val dragObserver = object : DragObserver {
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             offset.value += dragDistance
             return dragDistance
         }
     }
 
-    val onRelease: (PxPosition) -> Unit = {
+    val onRelease: (Offset) -> Unit = {
         dragInScale.value = !dragInScale.value
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressDragGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressDragGestureDetectorDemo.kt
index 8789973..7f2da76 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressDragGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressDragGestureDetectorDemo.kt
@@ -30,7 +30,7 @@
 import androidx.ui.layout.offset
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -39,13 +39,13 @@
 @Composable
 fun LongPressDragGestureFilterDemo() {
 
-    val offset = state { PxPosition.Origin }
+    val offset = state { Offset.Zero }
     val color = state { Grey }
 
     val longPressDragObserver =
         object : LongPressDragObserver {
 
-            override fun onLongPress(pxPosition: PxPosition) {
+            override fun onLongPress(pxPosition: Offset) {
                 color.value = Red
             }
 
@@ -54,12 +54,12 @@
                 color.value = Blue
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 offset.value += dragDistance
                 return dragDistance
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 color.value = Grey
             }
         }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressGestureDetectorDemo.kt
index d3b7e88..eaefe9b 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/LongPressGestureDetectorDemo.kt
@@ -28,7 +28,7 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -38,7 +38,7 @@
 fun LongPressGestureDetectorDemo() {
     val color = state { Colors.random() }
 
-    val onLongPress = { _: PxPosition ->
+    val onLongPress = { _: Offset ->
         color.value = color.value.anotherRandomColor()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedLongPressDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedLongPressDemo.kt
index 18b8835..1f42daf 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedLongPressDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedLongPressDemo.kt
@@ -28,7 +28,7 @@
 import androidx.ui.layout.Column
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.padding
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -65,7 +65,7 @@
     val currentColor = state { defaultColor }
     val pressed = state { false }
 
-    val onLongPress: (PxPosition) -> Unit = {
+    val onLongPress: (Offset) -> Unit = {
         currentColor.value = currentColor.value.next()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedPressDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedPressDemo.kt
index 4bf548f..25cb457 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedPressDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedPressDemo.kt
@@ -30,7 +30,7 @@
 import androidx.ui.layout.Column
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.padding
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -76,16 +76,16 @@
         pressed.value = false
     }
 
-    val onLongPress = { _: PxPosition ->
+    val onLongPress = { _: Offset ->
         pressed.value = false
         currentColor.value = defaultColor
     }
 
-    val onTap: (PxPosition) -> Unit = {
+    val onTap: (Offset) -> Unit = {
         currentColor.value = currentColor.value.next()
     }
 
-    val onDoubleTap = { _: PxPosition ->
+    val onDoubleTap = { _: Offset ->
         currentColor.value = currentColor.value.prev()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
index 5408a9a..ceb124b 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
@@ -41,7 +41,7 @@
 import androidx.ui.layout.preferredHeight
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import kotlin.math.roundToInt
@@ -82,7 +82,7 @@
     val maxOffset = state { 0f }
 
     val dragObserver = object : DragObserver {
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             val resultingOffset = offset.value + dragDistance.y
             val dyToConsume =
                 if (resultingOffset > 0f) {
@@ -93,7 +93,7 @@
                     dragDistance.y
                 }
             offset.value = offset.value + dyToConsume
-            return PxPosition(0f, dyToConsume)
+            return Offset(0f, dyToConsume)
         }
     }
 
@@ -143,7 +143,7 @@
     val color = state { defaultColor }
     val showPressed = state { false }
 
-    val onPress: (PxPosition) -> Unit = {
+    val onPress: (Offset) -> Unit = {
         showPressed.value = true
     }
 
@@ -151,15 +151,15 @@
         showPressed.value = false
     }
 
-    val onTap: (PxPosition) -> Unit = {
+    val onTap: (Offset) -> Unit = {
         color.value = color.value.next()
     }
 
-    val onDoubleTap: (PxPosition) -> Unit = {
+    val onDoubleTap: (Offset) -> Unit = {
         color.value = color.value.prev().prev()
     }
 
-    val onLongPress = { _: PxPosition ->
+    val onLongPress = { _: Offset ->
         color.value = defaultColor
         showPressed.value = false
     }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PopupDragDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PopupDragDemo.kt
index 7dd368a..c206424 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PopupDragDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PopupDragDemo.kt
@@ -33,7 +33,7 @@
 import androidx.ui.layout.Stack
 import androidx.ui.layout.preferredSize
 import androidx.ui.text.style.TextAlign
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.round
 
@@ -41,12 +41,12 @@
 fun PopupDragDemo() {
     // TODO fix this demo in RTL (check when draggable handles RTL)
     val offset = state {
-        PxPosition.Origin
+        Offset.Zero
     }
 
     val observer = remember {
         object : DragObserver {
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 offset.value = offset.value + dragDistance
                 return dragDistance
             }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PressIndicatorGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PressIndicatorGestureDetectorDemo.kt
index 1f952ed..554a62a 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PressIndicatorGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/PressIndicatorGestureDetectorDemo.kt
@@ -29,7 +29,7 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -39,7 +39,7 @@
 fun PressIndicatorGestureFilterDemo() {
     val pressed = state { false }
 
-    val onStart: (PxPosition) -> Unit = {
+    val onStart: (Offset) -> Unit = {
         pressed.value = true
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/RawDragGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/RawDragGestureDetectorDemo.kt
index 830b176..be9b685 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/RawDragGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/RawDragGestureDetectorDemo.kt
@@ -30,7 +30,7 @@
 import androidx.ui.layout.offset
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -38,10 +38,10 @@
  */
 @Composable
 fun RawDragGestureFilterDemo() {
-    val offset = state { PxPosition.Origin }
+    val offset = state { Offset.Zero }
 
     val dragObserver = object : DragObserver {
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             offset.value += dragDistance
             return dragDistance
         }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TapGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TapGestureDetectorDemo.kt
index 508a5cb..0cbe702 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TapGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TapGestureDetectorDemo.kt
@@ -28,7 +28,7 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -38,7 +38,7 @@
 fun TapGestureFilterDemo() {
     val color = state { Colors.random() }
 
-    val onTap: (PxPosition) -> Unit = {
+    val onTap: (Offset) -> Unit = {
         color.value = color.value.anotherRandomColor()
     }
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TouchSlopDragGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TouchSlopDragGestureDetectorDemo.kt
index 06868fe..6b7a6f7 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TouchSlopDragGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/TouchSlopDragGestureDetectorDemo.kt
@@ -32,7 +32,7 @@
 import androidx.ui.layout.offset
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 
 /**
@@ -44,32 +44,32 @@
     val verticalColor = Color(0xfff44336)
     val horizontalColor = Color(0xff2196f3)
 
-    val offset = state { PxPosition.Origin }
+    val offset = state { Offset.Zero }
     val canStartVertically = state { true }
 
     val dragObserver =
         if (canStartVertically.value) {
             object : DragObserver {
-                override fun onDrag(dragDistance: PxPosition): PxPosition {
+                override fun onDrag(dragDistance: Offset): Offset {
                     offset.value =
-                        PxPosition(x = offset.value.x, y = offset.value.y + dragDistance.y)
+                        Offset(x = offset.value.x, y = offset.value.y + dragDistance.y)
                     return dragDistance
                 }
 
-                override fun onStop(velocity: PxPosition) {
+                override fun onStop(velocity: Offset) {
                     canStartVertically.value = !canStartVertically.value
                     super.onStop(velocity)
                 }
             }
         } else {
             object : DragObserver {
-                override fun onDrag(dragDistance: PxPosition): PxPosition {
+                override fun onDrag(dragDistance: Offset): Offset {
                     offset.value =
-                        PxPosition(x = offset.value.x + dragDistance.x, y = offset.value.y)
+                        Offset(x = offset.value.x + dragDistance.x, y = offset.value.y)
                     return dragDistance
                 }
 
-                override fun onStop(velocity: PxPosition) {
+                override fun onStop(velocity: Offset) {
                     canStartVertically.value = !canStartVertically.value
                     super.onStop(velocity)
                 }
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/AndroidPointerInputTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/AndroidPointerInputTest.kt
index ac5ba57..be4e9b5 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/AndroidPointerInputTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/AndroidPointerInputTest.kt
@@ -29,11 +29,10 @@
 import androidx.compose.remember
 import androidx.compose.setValue
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
@@ -51,8 +50,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class AndroidPointerInputTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<AndroidPointerInputTestActivity>(
+    val rule = androidx.test.rule.ActivityTestRule<AndroidPointerInputTestActivity>(
         AndroidPointerInputTestActivity::class.java
     )
 
@@ -168,7 +168,7 @@
     fun dispatchTouchEvent_notMeasuredLayoutsAreMeasuredFirst() {
         val size = mutableStateOf(10)
         val latch = CountDownLatch(1)
-        var consumedDownPosition: PxPosition? = null
+        var consumedDownPosition: Offset? = null
         rule.runOnUiThread {
             container.setContent(Recomposer.current()) {
                 Layout(
@@ -210,7 +210,7 @@
             // we expect it to first remeasure and only then process
             androidComposeView.dispatchTouchEvent(motionEvent)
 
-            assertThat(consumedDownPosition).isEqualTo(PxPosition(15f, 15f))
+            assertThat(consumedDownPosition).isEqualTo(Offset(15f, 15f))
         }
     }
 
@@ -277,7 +277,7 @@
     PointerInputModifierImpl(filter)
 }
 
-fun Modifier.consumeDownGestureFilter(onDown: (PxPosition) -> Unit): Modifier = composed {
+fun Modifier.consumeDownGestureFilter(onDown: (Offset) -> Unit): Modifier = composed {
     val filter = remember { ConsumeDownChangeFilter() }
     filter.onDown = onDown
     this + PointerInputModifierImpl(filter)
@@ -305,7 +305,7 @@
 }
 
 private class ConsumeDownChangeFilter : PointerInputFilter() {
-    var onDown by mutableStateOf<(PxPosition) -> Unit>({})
+    var onDown by mutableStateOf<(Offset) -> Unit>({})
     override fun onPointerInput(
         changes: List<PointerInputChange>,
         pass: PointerEventPass,
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/MeasureAndLayoutDelegateTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/MeasureAndLayoutDelegateTest.kt
new file mode 100644
index 0000000..eb15787
--- /dev/null
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/MeasureAndLayoutDelegateTest.kt
@@ -0,0 +1,1480 @@
+/*
+ * 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.core
+
+import androidx.test.filters.SmallTest
+import androidx.ui.core.LayoutNode.LayoutState
+import androidx.ui.core.test.AndroidOwnerExtraAssertionsRule
+import androidx.ui.unit.IntPx
+import androidx.ui.unit.ipx
+import androidx.ui.unit.max
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.doAnswer
+import com.nhaarman.mockitokotlin2.mock
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class MeasureAndLayoutDelegateTest {
+
+    private val Size = 100
+    private val DifferentSize = 50
+    private val DifferentSize2 = 30
+
+    @get:Rule
+    val excessiveAssertions = AndroidOwnerExtraAssertionsRule()
+
+    @Test
+    fun requiresMeasureWhenJustCreated() {
+        val root = root {
+            add(node())
+        }
+
+        createDelegate(root, firstMeasureCompleted = false)
+
+        assertMeasureRequired(root)
+        assertMeasureRequired(root.first)
+    }
+
+    @Test
+    fun measureNotRequiredAfterFirstMeasure() {
+        val root = root {
+            add(node())
+        }
+
+        createDelegate(root)
+
+        assertMeasuredAndLaidOut(root)
+        assertMeasuredAndLaidOut(root.first)
+    }
+
+    @Test
+    fun relayoutNotRequiredAfterFirstMeasure() {
+        val root = root {
+            add(node())
+        }
+
+        createDelegate(root)
+
+        assertMeasuredAndLaidOut(root)
+        assertMeasuredAndLaidOut(root.first)
+    }
+
+    @Test
+    fun measuredAndLaidOutAfterFirstMeasureAndLayout() {
+        val root = root {
+            add(node())
+        }
+
+        assertRemeasured(root) {
+            assertRemeasured(root.first) {
+                createDelegate(root)
+            }
+        }
+    }
+
+    // remeasure request:
+
+    @Test
+    fun childRemeasureRequest_remeasureRequired() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        delegate.requestRemeasure(root.first)
+        assertMeasureRequired(root.first)
+    }
+
+    @Test
+    fun childRemeasureRequest_childRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childMeasuredInLayoutBlockRemeasureRequest_childRemeasured() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureWithTheSameResult_parentNotRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureWithDifferentResult_parentRemeasured() {
+        val root = root {
+            wrapChildren = true
+            add(node {
+                size = DifferentSize
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertRemeasured(root) {
+                root.first.size = DifferentSize2
+                delegate.requestRemeasure(root.first)
+                assertThat(delegate.measureAndLayout()).isTrue()
+            }
+        }
+    }
+
+    @Test
+    fun childRemeasureInLayoutBlockWithTheSameResult_parentNotRemeasured() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureInLayoutBlockWithDifferentResult_parentNotRemeasured() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            root.first.size = DifferentSize
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureRequest_childRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childMeasuredInLayoutBlockRelayoutRequest_childRelaidOut() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureWithTheSameResult_parentNotRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureInLayoutBlockWithTheSameResult_parentNotRelaidOut() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureInLayoutBlockWithDifferentResult_parentRelaidOut() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root) {
+            root.first.size = DifferentSize
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun rootRemeasureRequest_childNotAffected() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertNotRemeasured(root.first) {
+                assertNotRelaidOut(root.first) {
+                    delegate.requestRemeasure(root)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun parentRemeasureRequest_childNotAffected() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertNotRemeasured(root.first.first) {
+                assertNotRelaidOut(root.first.first) {
+                    delegate.requestRemeasure(root.first)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    // relayout request:
+
+    @Test
+    fun childRelayoutRequest_childRelayoutRequired() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        delegate.requestRelayout(root.first)
+        assertLayoutRequired(root.first)
+    }
+
+    @Test
+    fun childRelayoutRequest_childRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRelayoutRequest_childNotRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root.first) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRelayoutRequest_parentNotRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRelayoutRequest_parentNotRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childMeasuredInLayoutBlockRelayoutRequest_parentNotRemeasured() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childMeasuredInLayoutBlockRelayoutRequest_parentNotRelaidOut() {
+        val root = root {
+            add(node())
+            measureInLayoutBlock()
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun rootRelayoutRequest_childNotAffected() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root) {
+            assertNotRelaidOut(root.first) {
+                delegate.requestRelayout(root)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun parentRelayoutRequest_childNotAffected() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            assertNotRelaidOut(root.first.first) {
+                delegate.requestRelayout(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    // request twice
+
+    @Test
+    fun childRemeasureRequestedTwice_childRemeasuredOnce() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            delegate.requestRemeasure(root.first)
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureRequestedTwice_childRelaidOutOnce() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRemeasure(root.first)
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureAndRelayoutRequested_childRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            delegate.requestRemeasure(root.first)
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRemeasureAndRelayoutRequested_childRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRemeasure(root.first)
+            delegate.requestRelayout(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRelayoutAndRemeasureRequested_childRemeasured() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            delegate.requestRelayout(root.first)
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun childRelayoutAndRemeasureRequested_childRelaidOut() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            delegate.requestRelayout(root.first)
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    // Siblings
+
+    @Test
+    fun firstChildRemeasureRequest_onlyFirstChildRemeasured() {
+        val root = root {
+            add(node())
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertNotRemeasured(root.second) {
+                delegate.requestRemeasure(root.first)
+                delegate.measureAndLayout()
+            }
+        }
+    }
+
+    @Test
+    fun firstChildRelayoutRequest_onlyFirstChildRelaid() {
+        val root = root {
+            add(node())
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            assertNotRelaidOut(root.second) {
+                delegate.requestRelayout(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun bothChildrenRemeasureRequest_bothRemeasured() {
+        val root = root {
+            add(node())
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertRemeasured(root.second) {
+                delegate.requestRemeasure(root.first)
+                delegate.requestRemeasure(root.second)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun bothChildrenRelayoutRequest_bothRelaidOut() {
+        val root = root {
+            add(node())
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root.first) {
+            assertRelaidOut(root.second) {
+                delegate.requestRelayout(root.first)
+                delegate.requestRelayout(root.second)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun oneChildRelayoutRequestAnotherRemeasure() {
+        val root = root {
+            add(node())
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertNotRemeasured(root.second) {
+                assertRelaidOut(root.second) {
+                    delegate.requestRemeasure(root.first)
+                    delegate.requestRelayout(root.second)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    // different levels
+
+    @Test
+    fun remeasureTwoNodesOnDifferentLayers_othersAreNotAffected() {
+        val root = root {
+            add(node())
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            assertRemeasured(root.first) {
+                assertNotRemeasured(root.second) {
+                    assertRemeasured(root.second.first) {
+                        delegate.requestRemeasure(root.first)
+                        delegate.requestRemeasure(root.second.first)
+                        assertThat(delegate.measureAndLayout()).isFalse()
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun changeSizeOfTheLeaf_remeasuresUpToTheFixedSizeParent() {
+        val root = root {
+            wrapChildren = true
+            add(node {
+                size = DifferentSize
+                add(node {
+                    wrapChildren = true
+                    add(node {
+                        size = DifferentSize
+                    })
+                })
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            assertRemeasured(root.first) {
+                assertRemeasured(root.first.first) {
+                    val leaf = root.first.first.first
+                    assertRemeasured(leaf) {
+                        leaf.size = DifferentSize2
+                        delegate.requestRemeasure(leaf)
+                        assertThat(delegate.measureAndLayout()).isFalse()
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun remeasureRequestForItemsOnTheSameLevelButDifferentParents() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            assertNotRemeasured(root.first) {
+                assertRemeasured(root.first.first) {
+                    assertNotRemeasured(root.second) {
+                        assertRemeasured(root.second.first) {
+                            delegate.requestRemeasure(root.first.first)
+                            delegate.requestRemeasure(root.second.first)
+                            assertThat(delegate.measureAndLayout()).isFalse()
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun relayoutRequestForItemsOnTheSameLevelButDifferentParents() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            assertNotRelaidOut(root.first) {
+                assertRelaidOut(root.first.first) {
+                    assertNotRelaidOut(root.second) {
+                        assertRelaidOut(root.second.first) {
+                            delegate.requestRelayout(root.first.first)
+                            delegate.requestRelayout(root.second.first)
+                            assertThat(delegate.measureAndLayout()).isFalse()
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun relayoutAndRemeasureRequestForItemsOnTheSameLevelButDifferentParents() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRelaidOut(root) {
+            assertNotRelaidOut(root.first) {
+                assertRemeasured(root.first.first) {
+                    assertNotRelaidOut(root.second) {
+                        assertRelaidOut(root.second.first) {
+                            delegate.requestRemeasure(root.first.first)
+                            delegate.requestRelayout(root.second.first)
+                            assertThat(delegate.measureAndLayout()).isFalse()
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // request during measure
+
+    @Test
+    fun requestChildRemeasureDuringMeasure() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertRemeasured(root.first) {
+                root.runDuringMeasure {
+                    delegate.requestRemeasure(root.first)
+                }
+                delegate.requestRemeasure(root)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun requestGrandchildRemeasureDuringMeasure() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertNotRemeasured(root.first) {
+                assertRemeasured(root.first.first) {
+                    root.runDuringMeasure {
+                        delegate.requestRemeasure(root.first.first)
+                    }
+                    delegate.requestRemeasure(root)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun requestChildRelayoutDuringMeasure() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertRelaidOut(root.first) {
+                root.runDuringMeasure {
+                    delegate.requestRelayout(root.first)
+                }
+                delegate.requestRemeasure(root)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun requestGrandchildRelayoutDuringMeasure() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertNotRelaidOut(root.first) {
+                assertRelaidOut(root.first.first) {
+                    root.runDuringMeasure {
+                        delegate.requestRelayout(root.first.first)
+                    }
+                    delegate.requestRemeasure(root)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun requestChildRemeasureDuringParentLayout() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root) {
+            assertRemeasured(root.first) {
+                root.runDuringLayout {
+                    delegate.requestRemeasure(root.first)
+                }
+                delegate.requestRelayout(root)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun requestGrandchildRemeasureDuringParentLayout() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRelaidOut(root) {
+            assertNotRelaidOut(root.first) {
+                assertRemeasured(root.first.first) {
+                    root.runDuringLayout {
+                        delegate.requestRemeasure(root.first.first)
+                    }
+                    delegate.requestRelayout(root)
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun requestRemeasureForCurrentlyBeingRemeasuredNode() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            root.runDuringMeasure {
+                delegate.requestRemeasure(root.first)
+            }
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun requestRelayoutForCurrentlyBeingRemeasuredNode() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertRelaidOut(root.first) {
+                root.runDuringMeasure {
+                    delegate.requestRelayout(root.first)
+                }
+                delegate.requestRemeasure(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun requestRemeasureForCurrentlyBeingRelayoutNode() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertRelaidOut(root.first, times = 2) {
+                root.first.runDuringLayout {
+                    delegate.requestRemeasure(root.first)
+                }
+                delegate.requestRelayout(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    @Test
+    fun requestRelayoutForCurrentlyBeingRelayoutNode() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root.first) {
+            assertRelaidOut(root.first) {
+                root.runDuringLayout {
+                    delegate.requestRelayout(root.first)
+                }
+                delegate.requestRelayout(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    // Rtl
+
+    @Test
+    fun changeDirectionForChildren() {
+        val root = root {
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root, withDirection = LayoutDirection.Ltr) {
+            assertRemeasured(root.first, withDirection = LayoutDirection.Rtl) {
+                root.childrenDirection = LayoutDirection.Rtl
+                delegate.requestRemeasure(root)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    // Updating root constraints / layout direction
+
+    @Test
+    fun changingParentParamsToTheSameValue_noRemeasures() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            assertNotRemeasured(root.first) {
+                assertNotRemeasured(root.first.first) {
+                    delegate.updateRootParams(
+                        defaultRootConstraints(),
+                        LayoutDirection.Ltr
+                    )
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun changingParentConstraints_remeasureSubTree() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertRemeasured(root.first) {
+                assertRemeasured(root.first.first) {
+                    delegate.updateRootParams(
+                        Constraints(maxWidth = DifferentSize.ipx, maxHeight = DifferentSize.ipx),
+                        LayoutDirection.Ltr
+                    )
+                    assertThat(delegate.measureAndLayout()).isTrue()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun changingParentConstraints_remeasureOnlyAffectedNodes() {
+        val root = root {
+            add(node {
+                size = DifferentSize2
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root.first) {
+            assertNotRemeasured(root.first.first) {
+                delegate.updateRootParams(
+                    Constraints(maxWidth = DifferentSize.ipx, maxHeight = DifferentSize.ipx),
+                    LayoutDirection.Ltr
+                )
+                assertThat(delegate.measureAndLayout()).isTrue()
+            }
+        }
+    }
+
+    @Test
+    fun changingParentDirection_remeasureSubTree() {
+        val root = root {
+            add(node {
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root, withDirection = LayoutDirection.Rtl) {
+            assertRemeasured(root.first, withDirection = LayoutDirection.Rtl) {
+                assertRemeasured(root.first.first, withDirection = LayoutDirection.Rtl) {
+                    delegate.updateRootParams(
+                        defaultRootConstraints(),
+                        LayoutDirection.Rtl
+                    )
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun changingParentDirection_remeasureOnlyAffectedNodes() {
+        val root = root {
+            add(node {
+                childrenDirection = LayoutDirection.Rtl
+                add(node())
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root, withDirection = LayoutDirection.Rtl) {
+            assertRemeasured(root.first, withDirection = LayoutDirection.Rtl) {
+                assertNotRemeasured(root.first.first) {
+                    delegate.updateRootParams(
+                        defaultRootConstraints(),
+                        LayoutDirection.Rtl
+                    )
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    // LayoutModifier
+
+    @Test
+    fun requestRemeasureTriggersModifierRemeasure() {
+        val spyModifier = SpyLayoutModifier()
+        val root = root {
+            add(node {
+                modifier = spyModifier
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(spyModifier) {
+            delegate.requestRemeasure(root.first)
+            assertThat(delegate.measureAndLayout()).isFalse()
+        }
+    }
+
+    @Test
+    fun requestRelayoutTriggersModifierRelayout() {
+        val spyModifier = SpyLayoutModifier()
+        val root = root {
+            add(node {
+                modifier = spyModifier
+            })
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(spyModifier) {
+            assertRelaidOut(spyModifier) {
+                delegate.requestRelayout(root.first)
+                assertThat(delegate.measureAndLayout()).isFalse()
+            }
+        }
+    }
+
+    // Relayout depending on the measured child
+    // Illustrates the case when we run layoutChildren() on the parent node, but some of its
+    // children are not yet measured even if they are supposed to be measured in the measure
+    // block of our parent.
+    //
+    // Example:
+    // val child = Layout(...)
+    // Layout(child) { measuruables, constraints ->
+    //    val placeable = measurables.first().measure(constraints)
+    //    layout(placeable.width, placeable.height) {
+    //       placeable.place(0, 0)
+    //    }
+    // }
+    // Then some changes scheduled remeasure for child and relayout for parent.
+    // During the measureAndLayout() we will start with the parent as it has lower depth.
+    // Inside the layout block we will call placeable.width which is currently dirty as the child
+    // was scheduled to remeasure.
+
+    @Test
+    fun relayoutDependingOnRemeasuredChild() {
+        val root = root {
+            // this node will be measured in the measuring block
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertNotRemeasured(root) {
+            assertRelaidOut(root) {
+                assertRemeasured(root.first) {
+                    delegate.requestRemeasure(root.first)
+                    delegate.requestRelayout(root)
+                    root.runDuringLayout {
+                        // this means the root.first will be measured before laying out the root
+                        assertThat(root.first.layoutState).isEqualTo(LayoutState.NeedsRelayout)
+                    }
+                    assertThat(delegate.measureAndLayout()).isFalse()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun relayoutDependingOnRemeasuredChild_parentRemeasuredBecauseOfChangedSize() {
+        val root = root {
+            wrapChildren = true
+            // this node will be measured in the measuring block
+            add(node())
+        }
+
+        val delegate = createDelegate(root)
+
+        assertRemeasured(root) {
+            assertRemeasured(root.first) {
+                root.first.size = DifferentSize
+                delegate.requestRemeasure(root.first)
+                delegate.requestRelayout(root)
+                assertThat(delegate.measureAndLayout()).isTrue()
+            }
+        }
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    private fun createDelegate(
+        root: LayoutNode,
+        firstMeasureCompleted: Boolean = true
+    ): MeasureAndLayoutDelegate {
+        val delegate = MeasureAndLayoutDelegate(root)
+        root.attach(mock {
+            on { measureIteration } doAnswer {
+                delegate.measureIteration
+            }
+            on { onRequestMeasure(any()) } doAnswer {
+                delegate.requestRemeasure(it.arguments[0] as LayoutNode)
+                Unit
+            }
+            on { observeMeasureModelReads(any(), any()) } doAnswer {
+                (it.arguments[1] as () -> Unit).invoke()
+            }
+            on { observeLayoutModelReads(any(), any()) } doAnswer {
+                (it.arguments[1] as () -> Unit).invoke()
+            }
+        })
+        if (firstMeasureCompleted) {
+            delegate.updateRootParams(
+                defaultRootConstraints(),
+                LayoutDirection.Ltr
+            )
+            assertThat(delegate.measureAndLayout()).isTrue()
+        }
+        return delegate
+    }
+
+    private fun defaultRootConstraints() = Constraints(maxWidth = Size.ipx, maxHeight = Size.ipx)
+
+    private fun assertNotRemeasured(node: LayoutNode, block: (LayoutNode) -> Unit) {
+        val measuresCountBefore = node.measuresCount
+        block(node)
+        assertThat(node.measuresCount).isEqualTo(measuresCountBefore)
+        assertMeasuredAndLaidOut(node)
+    }
+
+    private fun assertRemeasured(
+        node: LayoutNode,
+        times: Int = 1,
+        withDirection: LayoutDirection? = null,
+        block: (LayoutNode) -> Unit
+    ) {
+        val measuresCountBefore = node.measuresCount
+        block(node)
+        assertThat(node.measuresCount).isEqualTo(measuresCountBefore + times)
+        if (withDirection != null) {
+            assertThat(node.measuredWithLayoutDirection).isEqualTo(withDirection)
+        }
+        assertMeasuredAndLaidOut(node)
+    }
+
+    private fun assertRelaidOut(node: LayoutNode, times: Int = 1, block: (LayoutNode) -> Unit) {
+        val layoutsCountBefore = node.layoutsCount
+        block(node)
+        assertThat(node.layoutsCount).isEqualTo(layoutsCountBefore + times)
+        assertMeasuredAndLaidOut(node)
+    }
+
+    private fun assertNotRelaidOut(node: LayoutNode, block: (LayoutNode) -> Unit) {
+        val layoutsCountBefore = node.layoutsCount
+        block(node)
+        assertThat(node.layoutsCount).isEqualTo(layoutsCountBefore)
+        assertMeasuredAndLaidOut(node)
+    }
+
+    private fun assertMeasureRequired(node: LayoutNode) {
+        assertThat(node.layoutState).isEqualTo(LayoutState.NeedsRemeasure)
+    }
+
+    private fun assertMeasuredAndLaidOut(node: LayoutNode) {
+        assertThat(node.layoutState).isEqualTo(LayoutState.Ready)
+    }
+
+    private fun assertLayoutRequired(node: LayoutNode) {
+        assertThat(node.layoutState).isEqualTo(LayoutState.NeedsRelayout)
+    }
+
+    private fun assertRemeasured(
+        modifier: SpyLayoutModifier,
+        block: () -> Unit
+    ) {
+        val measuresCountBefore = modifier.measuresCount
+        block()
+        assertThat(modifier.measuresCount).isEqualTo(measuresCountBefore + 1)
+    }
+
+    private fun assertNotRemeasured(
+        modifier: SpyLayoutModifier,
+        block: () -> Unit
+    ) {
+        val measuresCountBefore = modifier.measuresCount
+        block()
+        assertThat(modifier.measuresCount).isEqualTo(measuresCountBefore)
+    }
+
+    private fun assertRelaidOut(
+        modifier: SpyLayoutModifier,
+        block: () -> Unit
+    ) {
+        val layoutsCountBefore = modifier.layoutsCount
+        block()
+        assertThat(modifier.layoutsCount).isEqualTo(layoutsCountBefore + 1)
+    }
+
+    private fun root(block: LayoutNode.() -> Unit = {}): LayoutNode {
+        return node(block).apply {
+            isPlaced = true
+        }
+    }
+
+    private fun node(block: LayoutNode.() -> Unit = {}): LayoutNode {
+        return LayoutNode().apply {
+            measureBlocks = MeasureInMeasureBlock()
+            block.invoke(this)
+        }
+    }
+}
+
+private fun LayoutNode.add(child: LayoutNode) = insertAt(children.count(), child)
+private fun LayoutNode.measureInLayoutBlock() {
+    measureBlocks = MeasureInLayoutBlock()
+}
+
+private fun LayoutNode.runDuringMeasure(block: () -> Unit) {
+    (measureBlocks as SmartMeasureBlock).preMeasureCallback = block
+}
+
+private fun LayoutNode.runDuringLayout(block: () -> Unit) {
+    (measureBlocks as SmartMeasureBlock).preLayoutCallback = block
+}
+
+private val LayoutNode.first: LayoutNode get() = children.first()
+private val LayoutNode.second: LayoutNode get() = children[1]
+private val LayoutNode.measuresCount: Int
+    get() = (measureBlocks as SmartMeasureBlock).measuresCount
+private val LayoutNode.layoutsCount: Int
+    get() = (measureBlocks as SmartMeasureBlock).layoutsCount
+private var LayoutNode.wrapChildren: Boolean
+    get() = (measureBlocks as SmartMeasureBlock).wrapChildren
+    set(value) {
+        (measureBlocks as SmartMeasureBlock).wrapChildren = value
+    }
+private val LayoutNode.measuredWithLayoutDirection: LayoutDirection
+    get() = (measureBlocks as SmartMeasureBlock).measuredLayoutDirection!!
+private var LayoutNode.size: Int?
+    get() = (measureBlocks as SmartMeasureBlock).size
+    set(value) {
+        (measureBlocks as SmartMeasureBlock).size = value
+    }
+private var LayoutNode.childrenDirection: LayoutDirection?
+    get() = (measureBlocks as SmartMeasureBlock).childrenLayoutDirection
+    set(value) {
+        (measureBlocks as SmartMeasureBlock).childrenLayoutDirection = value
+    }
+
+abstract class SmartMeasureBlock : LayoutNode.NoIntrinsicsMeasureBlocks("") {
+    var measuresCount = 0
+        protected set
+    var layoutsCount = 0
+        protected set
+    open var wrapChildren = false
+    var preMeasureCallback: (() -> Unit)? = null
+    var preLayoutCallback: (() -> Unit)? = null
+    var measuredLayoutDirection: LayoutDirection? = null
+        protected set
+    var childrenLayoutDirection: LayoutDirection? = null
+    // child size is used when null
+    var size: Int? = null
+}
+
+private class MeasureInMeasureBlock : SmartMeasureBlock() {
+    override fun measure(
+        measureScope: MeasureScope,
+        measurables: List<Measurable>,
+        constraints: Constraints,
+        layoutDirection: LayoutDirection
+    ): MeasureScope.MeasureResult {
+        measuresCount++
+        measuredLayoutDirection = layoutDirection
+        preMeasureCallback?.invoke()
+        preMeasureCallback = null
+        val childConstraints = if (size == null) {
+            constraints
+        } else {
+            val size = size!!.ipx
+            constraints.copy(maxWidth = size, maxHeight = size)
+        }
+        val placeables = measurables.map {
+            it.measure(childConstraints, childrenLayoutDirection ?: layoutDirection)
+        }
+        var maxWidth = IntPx.Zero
+        var maxHeight = IntPx.Zero
+        if (!wrapChildren) {
+            maxWidth = childConstraints.maxWidth
+            maxHeight = childConstraints.maxHeight
+        } else {
+            placeables.forEach { placeable ->
+                maxWidth = max(placeable.width, maxWidth)
+                maxHeight = max(placeable.height, maxHeight)
+            }
+        }
+        return measureScope.layout(maxWidth, maxHeight) {
+            layoutsCount++
+            preLayoutCallback?.invoke()
+            preLayoutCallback = null
+            placeables.forEach { placeable ->
+                placeable.place(IntPx.Zero, IntPx.Zero)
+            }
+        }
+    }
+}
+
+private class MeasureInLayoutBlock : SmartMeasureBlock() {
+
+    override var wrapChildren: Boolean
+        get() = false
+        set(value) {
+            if (value) {
+                throw IllegalArgumentException("MeasureInLayoutBlock always fills the parent size")
+            }
+        }
+
+    override fun measure(
+        measureScope: MeasureScope,
+        measurables: List<Measurable>,
+        constraints: Constraints,
+        layoutDirection: LayoutDirection
+    ): MeasureScope.MeasureResult {
+        measuresCount++
+        measuredLayoutDirection = layoutDirection
+        preMeasureCallback?.invoke()
+        preMeasureCallback = null
+        val childConstraints = if (size == null) {
+            constraints
+        } else {
+            val size = size!!.ipx
+            constraints.copy(maxWidth = size, maxHeight = size)
+        }
+        return measureScope.layout(childConstraints.maxWidth, childConstraints.maxHeight) {
+            preLayoutCallback?.invoke()
+            preLayoutCallback = null
+            layoutsCount++
+            measurables.forEach {
+                it.measure(childConstraints, childrenLayoutDirection ?: layoutDirection)
+                    .place(IntPx.Zero, IntPx.Zero)
+            }
+        }
+    }
+}
+
+private class SpyLayoutModifier : LayoutModifier {
+    var measuresCount = 0
+    var layoutsCount = 0
+
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints,
+        layoutDirection: LayoutDirection
+    ): MeasureScope.MeasureResult {
+        measuresCount++
+        return layout(constraints.maxWidth, constraints.maxHeight) {
+            layoutsCount++
+            measurable.measure(constraints).place(0.ipx, 0.ipx)
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/PainterModifierTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/PainterModifierTest.kt
index 4eae0ed..c3be581 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/PainterModifierTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/PainterModifierTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.Composable
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.test.AlignTopLeft
 import androidx.ui.core.test.AtLeastSize
 import androidx.ui.core.test.FixedSize
@@ -61,8 +60,9 @@
     val containerWidth = 100.0f
     val containerHeight = 100.0f
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
     private lateinit var drawLatch: CountDownLatch
 
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/ClearFocusTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/ClearFocusTest.kt
new file mode 100644
index 0000000..dcdb746
--- /dev/null
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/ClearFocusTest.kt
@@ -0,0 +1,273 @@
+/*
+ * 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.core.focus
+
+import androidx.test.filters.SmallTest
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.ActiveParent
+import androidx.ui.core.focus.FocusDetailedState.Captured
+import androidx.ui.core.focus.FocusDetailedState.Disabled
+import androidx.ui.core.focus.FocusDetailedState.Inactive
+import androidx.ui.foundation.Box
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.runOnIdleCompose
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@SmallTest
+@RunWith(Parameterized::class)
+class ClearFocusTest(val forcedClear: Boolean) {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "forcedClear = {0}")
+        fun initParameters() = listOf(true, false)
+    }
+
+    @Test
+    fun active_isCleared() {
+        // Arrange.
+        val modifier = FocusModifierImpl(Active)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun active_isClearedAndRemovedFromParentsFocusedChild() {
+        // Arrange.
+        val parent = FocusModifierImpl(ActiveParent)
+        val modifier = FocusModifierImpl(Active)
+        composeTestRule.setFocusableContent {
+            Box(modifier = parent) {
+                Box(modifier = modifier)
+            }
+            parent.focusedChild = modifier.focusNode
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(parent.focusedChild).isNull()
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun activeParent_noFocusedChild_throwsException() {
+        // Arrange.
+        val modifier = FocusModifierImpl(ActiveParent)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+    }
+
+    @Test
+    fun activeParent_isClearedAndRemovedFromParentsFocusedChild() {
+        // Arrange.
+        val parent = FocusModifierImpl(ActiveParent)
+        val modifier = FocusModifierImpl(ActiveParent)
+        val child = FocusModifierImpl(Active)
+        composeTestRule.setFocusableContent {
+            Box(modifier = parent) {
+                Box(modifier = modifier) {
+                    Box(modifier = child)
+                }
+            }
+            parent.focusedChild = modifier.focusNode
+            modifier.focusedChild = child.focusNode
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(modifier.focusedChild).isNull()
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun activeParent_clearsEntireHierarchy() {
+        // Arrange.
+        val modifier = FocusModifierImpl(ActiveParent)
+        val child = FocusModifierImpl(ActiveParent)
+        val grandchild = FocusModifierImpl(ActiveParent)
+        val greatgrandchild = FocusModifierImpl(Active)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier) {
+                Box(modifier = child) {
+                    Box(modifier = grandchild) {
+                        Box(modifier = greatgrandchild)
+                    }
+                }
+            }
+            modifier.focusedChild = child.focusNode
+            child.focusedChild = grandchild.focusNode
+            grandchild.focusedChild = greatgrandchild.focusNode
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(modifier.focusedChild).isNull()
+            assertThat(child.focusedChild).isNull()
+            assertThat(grandchild.focusedChild).isNull()
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+            assertThat(child.focusDetailedState).isEqualTo(Inactive)
+            assertThat(grandchild.focusDetailedState).isEqualTo(Inactive)
+            assertThat(greatgrandchild.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun captured_isCleared_whenForced() {
+        // Arrange.
+        val modifier = FocusModifierImpl(Captured)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            when (forcedClear) {
+                true -> {
+                    assertThat(cleared).isTrue()
+                    assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+                }
+                false -> {
+                    assertThat(cleared).isFalse()
+                    assertThat(modifier.focusDetailedState).isEqualTo(Captured)
+                }
+            }
+        }
+    }
+
+    @Test
+    fun active_isClearedAndRemovedFromParentsFocusedChild_whenForced() {
+        // Arrange.
+        val parent = FocusModifierImpl(ActiveParent)
+        val modifier = FocusModifierImpl(Captured)
+        composeTestRule.setFocusableContent {
+            Box(modifier = parent) {
+                Box(modifier = modifier)
+            }
+            parent.focusedChild = modifier.focusNode
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            when (forcedClear) {
+                true -> {
+                    assertThat(cleared).isTrue()
+                    assertThat(parent.focusedChild).isNull()
+                    assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+                }
+                false -> {
+                    assertThat(cleared).isFalse()
+                    assertThat(parent.focusedChild).isEqualTo(modifier.focusNode)
+                    assertThat(modifier.focusDetailedState).isEqualTo(Captured)
+                }
+            }
+        }
+    }
+
+    @Test
+    fun Inactive_isUnchanged() {
+        // Arrange.
+        val modifier = FocusModifierImpl(Inactive)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun Disabled_isUnchanged() {
+        // Arrange.
+        val modifier = FocusModifierImpl(Disabled)
+        composeTestRule.setFocusableContent {
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        val cleared = runOnIdleCompose {
+            modifier.focusNode!!.clearFocus(forcedClear)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(cleared).isTrue()
+            assertThat(modifier.focusDetailedState).isEqualTo(Disabled)
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/OwnerFocusTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/OwnerFocusTest.kt
new file mode 100644
index 0000000..d4bce6f
--- /dev/null
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/OwnerFocusTest.kt
@@ -0,0 +1,158 @@
+/*
+ * 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.core.focus
+
+import android.view.ViewGroup
+import androidx.compose.Composable
+import androidx.test.filters.SmallTest
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.Inactive
+import androidx.ui.core.OwnerAmbient
+import androidx.ui.foundation.Box
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.runOnIdleCompose
+import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class OwnerFocusTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @Test
+    fun requestFocus_bringsViewInFocus() {
+        // Arrange.
+        lateinit var ownerView: ViewGroup
+        val modifier = FocusModifierImpl(Inactive)
+        composeTestRule.setFocusableContent {
+            ownerView = getOwner()
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        runOnIdleCompose {
+            modifier.requestFocus()
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(ownerView.isFocused).isTrue()
+        }
+    }
+
+    @Ignore("Enable this test after the owner propagates focus to the hierarchy (b/152535715)")
+    @Test
+    fun whenOwnerGainsFocus_focusModifiersAreUpdated() {
+        // Arrange.
+        lateinit var ownerView: ViewGroup
+        val modifier = FocusModifierImpl(Inactive)
+        composeTestRule.setFocusableContent {
+            ownerView = getOwner()
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        runOnIdleCompose {
+            ownerView.requestFocus()
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(modifier.focusDetailedState).isEqualTo(Active)
+        }
+    }
+
+    @Ignore("Enable this test after the owner propagates focus to the hierarchy (b/152535715)")
+    @Test
+    fun whenWindowGainsFocus_focusModifiersAreUpdated() {
+        // Arrange.
+        lateinit var ownerView: ViewGroup
+        val modifier = FocusModifierImpl(Inactive)
+        composeTestRule.setFocusableContent {
+            ownerView = getOwner()
+            Box(modifier = modifier)
+        }
+
+        // Act.
+        runOnIdleCompose {
+            ownerView.dispatchWindowFocusChanged(true)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(modifier.focusDetailedState).isEqualTo(Active)
+        }
+    }
+
+    @Test
+    fun whenOwnerLosesFocus_focusModifiersAreUpdated() {
+        // Arrange.
+        lateinit var ownerView: ViewGroup
+        val modifier = FocusModifierImpl(Inactive)
+        composeTestRule.setFocusableContent {
+            ownerView = getOwner()
+            Box(modifier = modifier)
+        }
+        runOnIdleCompose {
+            modifier.requestFocus()
+        }
+
+        // Act.
+        runOnIdleCompose {
+            ownerView.clearFocus()
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(modifier.focusDetailedState).isEqualTo(Inactive)
+        }
+    }
+
+    @Test
+    fun whenWindowLosesFocus_focusStateIsUnchanged() {
+        // Arrange.
+        lateinit var ownerView: ViewGroup
+        lateinit var modifier: FocusModifier
+        composeTestRule.setFocusableContent {
+            ownerView = getOwner()
+            modifier = FocusModifier()
+            Box(modifier = modifier)
+        }
+        runOnIdleCompose {
+            modifier.requestFocus()
+        }
+
+        // Act.
+        runOnIdleCompose {
+            ownerView.dispatchWindowFocusChanged(false)
+        }
+
+        // Assert.
+        runOnIdleCompose {
+            assertThat(modifier.focusDetailedState).isEqualTo(Active)
+        }
+    }
+
+    @Suppress("DEPRECATION")
+    @Composable
+    private fun getOwner() = OwnerAmbient.current as ViewGroup
+}
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/LongPressDragGestureFilterTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/LongPressDragGestureFilterTest.kt
index 2f232b7..14c1313 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/LongPressDragGestureFilterTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/LongPressDragGestureFilterTest.kt
@@ -20,13 +20,12 @@
 import android.view.ViewGroup
 import androidx.compose.emptyContent
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.layout.Stack
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.inOrder
@@ -50,8 +49,11 @@
 @LargeTest
 @RunWith(JUnit4::class)
 class LongPressDragGestureFilterTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private lateinit var longPressDragObserver: LongPressDragObserver
     private lateinit var longPressCountDownLatch: CountDownLatch
     private lateinit var view: View
@@ -371,15 +373,15 @@
 
 @Suppress("RedundantOverride")
 open class MyLongPressDragObserver(val onLongPress: () -> Unit) : LongPressDragObserver {
-    override fun onLongPress(pxPosition: PxPosition) {
+    override fun onLongPress(pxPosition: Offset) {
         onLongPress()
     }
 
     override fun onDragStart() {}
 
-    override fun onDrag(dragDistance: PxPosition): PxPosition {
+    override fun onDrag(dragDistance: Offset): Offset {
         return super.onDrag(dragDistance)
     }
 
-    override fun onStop(velocity: PxPosition) {}
+    override fun onStop(velocity: Offset) {}
 }
\ No newline at end of file
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/ScaleGestureFilterTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/ScaleGestureFilterTest.kt
index 4d02809..7772258 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/ScaleGestureFilterTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/ScaleGestureFilterTest.kt
@@ -20,7 +20,6 @@
 import android.view.ViewGroup
 import androidx.compose.emptyContent
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
@@ -48,8 +47,11 @@
 @LargeTest
 @RunWith(JUnit4::class)
 class ScaleGestureFilterTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private lateinit var scaleObserver: ScaleObserver
     private lateinit var view: View
     private var touchSlop: Float = Float.NEGATIVE_INFINITY
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/TouchSlopDragGestureFilterTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/TouchSlopDragGestureFilterTest.kt
index f26061c1..49c8cc3 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/TouchSlopDragGestureFilterTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/TouchSlopDragGestureFilterTest.kt
@@ -19,14 +19,13 @@
 import android.view.View
 import android.view.ViewGroup
 import androidx.test.filters.LargeTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.layout.Stack
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.inOrder
@@ -45,8 +44,11 @@
 @LargeTest
 @RunWith(JUnit4::class)
 class TouchSlopDragGestureFilterTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
     private lateinit var dragObserver: DragObserver
     private lateinit var view: View
     private var touchSlop: Float = Float.NEGATIVE_INFINITY
@@ -130,7 +132,7 @@
         }
 
         dragObserver.inOrder {
-            verify().onStart(PxPosition(50.ipx, 50.ipx))
+            verify().onStart(Offset(50f, 50f))
             // Twice because RawDragGestureDetector calls the callback on both postUp and postDown
             // and nothing consumes the drag distance.
             verify(dragObserver, times(2)).onDrag(any())
@@ -177,7 +179,7 @@
         }
 
         dragObserver.inOrder {
-            verify().onStart(PxPosition(50.ipx, 50.ipx))
+            verify().onStart(Offset(50f, 50f))
             // Twice because RawDragGestureDetector calls the callback on both postUp and postDown
             // and nothing consumes the drag distance.
             verify(dragObserver, times(2)).onDrag(any())
@@ -204,7 +206,7 @@
         }
 
         dragObserver.inOrder {
-            verify().onStart(PxPosition(50.ipx, 50.ipx))
+            verify().onStart(Offset(50f, 50f))
         }
         verifyNoMoreInteractions(dragObserver)
     }
@@ -238,7 +240,7 @@
             view.dispatchTouchEvent(move)
         }
 
-        verify(dragObserver, times(2)).onDrag(PxPosition(movement.toFloat(), 0.0f))
+        verify(dragObserver, times(2)).onDrag(Offset(movement.toFloat(), 0.0f))
     }
 
     private fun setup(startDragImmediately: Boolean) {
@@ -275,15 +277,15 @@
 
 @Suppress("RedundantOverride")
 open class MyDragObserver : DragObserver {
-    override fun onStart(downPosition: PxPosition) {
+    override fun onStart(downPosition: Offset) {
         super.onStart(downPosition)
     }
 
-    override fun onDrag(dragDistance: PxPosition): PxPosition {
+    override fun onDrag(dragDistance: Offset): Offset {
         return super.onDrag(dragDistance)
     }
 
-    override fun onStop(velocity: PxPosition) {
+    override fun onStop(velocity: Offset) {
         super.onStop(velocity)
     }
 }
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/utils.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/utils.kt
index e74b53a5..d50e43b 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/utils.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/gesture/utils.kt
@@ -17,10 +17,10 @@
 package androidx.ui.core.gesture
 
 import android.view.MotionEvent
-import androidx.test.rule.ActivityTestRule
 
 // We only need this because IR compiler doesn't like converting lambdas to Runnables
-internal fun ActivityTestRule<*>.runOnUiThreadIR(block: () -> Unit) {
+@Suppress("DEPRECATION")
+internal fun androidx.test.rule.ActivityTestRule<*>.runOnUiThreadIR(block: () -> Unit) {
     val runnable: Runnable = object : Runnable {
         override fun run() {
             block()
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/selection/SelectionHandlesTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/selection/SelectionHandlesTest.kt
index 574bdc9..299ab1f 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/selection/SelectionHandlesTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/selection/SelectionHandlesTest.kt
@@ -19,7 +19,6 @@
 import android.os.Build
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.setContent
 import androidx.ui.core.test.runOnUiThreadIR
 import androidx.ui.core.test.waitAndScreenShot
@@ -39,8 +38,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class SelectionHandlesTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
 
     private val HANDLE_COLOR = Color(0xFF2B28F5.toInt())
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index 65134c0..47686f0 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -39,7 +39,6 @@
 import androidx.compose.state
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.ContentDrawScope
 import androidx.ui.core.DrawLayerModifier
@@ -107,8 +106,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class AndroidLayoutDrawTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     @get:Rule
@@ -1096,7 +1096,7 @@
         layoutLatch = CountDownLatch(1)
         activityTestRule.runOnUiThreadIR { offset.value = 20.ipx }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        assertEquals(2, measure)
+        assertEquals(1, measure)
         assertEquals(2, layout)
         assertEquals(20.ipx, linePosition)
     }
@@ -2632,7 +2632,8 @@
     }
 }
 
-fun ActivityTestRule<*>.validateSquareColors(
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<*>.validateSquareColors(
     drawLatch: CountDownLatch,
     outerColor: Color,
     innerColor: Color,
@@ -3015,8 +3016,9 @@
     var innerColor: Color by mutableStateOf(innerColor)
 }
 
+@Suppress("DEPRECATION")
 // We only need this because IR compiler doesn't like converting lambdas to Runnables
-fun ActivityTestRule<*>.runOnUiThreadIR(block: () -> Unit) {
+fun androidx.test.rule.ActivityTestRule<*>.runOnUiThreadIR(block: () -> Unit) {
     val runnable: Runnable = object : Runnable {
         override fun run() {
             block()
@@ -3025,7 +3027,8 @@
     runOnUiThread(runnable)
 }
 
-fun ActivityTestRule<*>.findAndroidComposeView(): ViewGroup {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<*>.findAndroidComposeView(): ViewGroup {
     val contentViewGroup = activity.findViewById<ViewGroup>(android.R.id.content)
     return findAndroidComposeView(contentViewGroup)!!
 }
@@ -3047,8 +3050,11 @@
     return null
 }
 
+@Suppress("DEPRECATION")
 @RequiresApi(Build.VERSION_CODES.O)
-fun ActivityTestRule<*>.waitAndScreenShot(forceInvalidate: Boolean = true): Bitmap {
+fun androidx.test.rule.ActivityTestRule<*>.waitAndScreenShot(
+    forceInvalidate: Boolean = true
+): Bitmap {
     val view = findAndroidComposeView()
     val flushListener = DrawCounterListener(view)
     val offset = intArrayOf(0, 0)
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ClipTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ClipTest.kt
index e05ff33..552974f 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ClipTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ClipTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.DrawLayerModifier
 import androidx.ui.core.Modifier
 import androidx.ui.core.clip
@@ -56,8 +55,9 @@
 @RunWith(JUnit4::class)
 class ClipTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
     private lateinit var drawLatch: CountDownLatch
 
@@ -162,7 +162,7 @@
     fun roundedUniformRectClip() {
         val shape = object : Shape {
             override fun createOutline(size: Size, density: Density): Outline =
-                    Outline.Rounded(RRect(size.toRect(), Radius.circular(12f)))
+                    Outline.Rounded(RRect(size.toRect(), Radius(12f)))
         }
         rule.runOnUiThreadIR {
             activity.setContent {
@@ -197,10 +197,10 @@
             override fun createOutline(size: Size, density: Density): Outline =
                 Outline.Rounded(
                     RRect(size.toRect(),
-                        Radius.zero,
-                        Radius.circular(12f),
-                        Radius.circular(12f),
-                        Radius.circular(12f))
+                        Radius.Zero,
+                        Radius(12f),
+                        Radius(12f),
+                        Radius(12f))
                 )
         }
         rule.runOnUiThreadIR {
@@ -296,7 +296,7 @@
         rule.runOnUiThreadIR {
             model.value = object : Shape {
                 override fun createOutline(size: Size, density: Density): Outline =
-                    Outline.Rounded(RRect(size.toRect(), Radius.circular(12f)))
+                    Outline.Rounded(RRect(size.toRect(), Radius(12f)))
             }
         }
 
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawLayerTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawLayerTest.kt
index a5a6d81..00e1175 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawLayerTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawLayerTest.kt
@@ -17,7 +17,6 @@
 package androidx.ui.core.test
 
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
 import androidx.ui.core.TransformOrigin
@@ -30,7 +29,7 @@
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.height
 import androidx.ui.unit.ipx
 import androidx.ui.unit.width
@@ -47,8 +46,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class DrawLayerTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
 
@@ -79,7 +79,7 @@
 
         assertTrue(positionLatch.await(1, TimeUnit.SECONDS))
         activity.runOnUiThread {
-            assertEquals(PxPosition(10f, 10f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(10f, 10f), layoutCoordinates.positionInRoot)
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(10f, 10f, 40f, 40f), bounds)
             val global = layoutCoordinates.globalBounds
@@ -109,7 +109,7 @@
         activity.runOnUiThread {
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(5f, 0f, 25f, 30f), bounds)
-            assertEquals(PxPosition(5f, 0f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(5f, 0f), layoutCoordinates.positionInRoot)
         }
     }
 
@@ -131,7 +131,7 @@
         activity.runOnUiThread {
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(0f, 10f, 30f, 20f), bounds)
-            assertEquals(PxPosition(30f, 10f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(30f, 10f), layoutCoordinates.positionInRoot)
         }
     }
 
@@ -154,7 +154,7 @@
         activity.runOnUiThread {
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(20f, 10f, 30f, 20f), bounds)
-            assertEquals(PxPosition(30f, 10f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(30f, 10f), layoutCoordinates.positionInRoot)
         }
     }
 
@@ -177,7 +177,7 @@
         activity.runOnUiThread {
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(15f, 18f, 25f, 28f), bounds)
-            assertEquals(PxPosition(15f, 18f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(15f, 18f), layoutCoordinates.positionInRoot)
         }
     }
 
@@ -202,7 +202,7 @@
             val bounds = layoutCoordinates.boundsInRoot
             assertEquals(PxBounds(10f, 10f, 20f, 20f), bounds)
             // Positions aren't clipped
-            assertEquals(PxPosition(5f, 10f), layoutCoordinates.positionInRoot)
+            assertEquals(Offset(5f, 10f), layoutCoordinates.positionInRoot)
         }
     }
 
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawReorderingTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawReorderingTest.kt
index ffa9f55..4306bd0 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawReorderingTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawReorderingTest.kt
@@ -26,7 +26,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.DrawLayerModifier
 import androidx.ui.core.Layout
@@ -53,8 +52,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class DrawReorderingTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     @get:Rule
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawShadowTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawShadowTest.kt
index f3c685c..6d66d0bc5 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawShadowTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/DrawShadowTest.kt
@@ -23,7 +23,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Modifier
 import androidx.ui.core.drawBehind
 import androidx.ui.core.drawLayer
@@ -55,8 +54,9 @@
 @RunWith(JUnit4::class)
 class DrawShadowTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
     private lateinit var drawLatch: CountDownLatch
 
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayerTouchTransformTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayerTouchTransformTest.kt
index b222ede..e8c3afc 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayerTouchTransformTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayerTouchTransformTest.kt
@@ -41,7 +41,7 @@
 import androidx.ui.test.doPartialGesture
 import androidx.ui.test.findByTag
 import androidx.ui.test.sendDown
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.max
@@ -67,7 +67,7 @@
         var latch: CountDownLatch? = null
         rule.setContent {
             val pressed = state { false }
-            val onStart: (PxPosition) -> Unit = {
+            val onStart: (Offset) -> Unit = {
                 pressed.value = true
             }
 
@@ -122,7 +122,7 @@
         // however, after transformations, this point will be within
         // its bounds
 
-        val mappedPosition = PxPosition(342.0f, 168.0f)
+        val mappedPosition = Offset(342.0f, 168.0f)
         val node = findByTag(testTag).doPartialGesture { sendDown(mappedPosition) }
 
         latch = CountDownLatch(1).apply {
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayoutTagTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayoutTagTest.kt
index 448ca22..350815a 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayoutTagTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/LayoutTagTest.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.emptyContent
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.setContent
@@ -39,8 +38,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class LayoutTagTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
 
     @Before
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
index 95cb933..a89f1ff 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
@@ -20,7 +20,6 @@
 import androidx.compose.MutableState
 import androidx.compose.mutableStateOf
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.drawBehind
@@ -42,8 +41,9 @@
 @RunWith(JUnit4::class)
 class ModelReadsTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     @get:Rule
     val excessiveAssertions = AndroidOwnerExtraAssertionsRule()
     private lateinit var activity: TestActivity
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OnPositionedTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OnPositionedTest.kt
index 77fec16..d5077cc 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OnPositionedTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OnPositionedTest.kt
@@ -20,7 +20,6 @@
 import androidx.compose.mutableStateOf
 import androidx.compose.setValue
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
@@ -32,9 +31,8 @@
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
-import androidx.ui.unit.toPx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -50,8 +48,9 @@
 @RunWith(JUnit4::class)
 class OnPositionedTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
 
     @Before
@@ -96,13 +95,13 @@
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
         assertEquals(0f, wrap1Position)
-        assertEquals(size.toPx().value, wrap2Position)
+        assertEquals(size.value.toFloat(), wrap2Position)
         latch = CountDownLatch(2)
         rule.runOnUiThread {
             index = 1
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
-        assertEquals(size.toPx().value, wrap1Position)
+        assertEquals(size.value.toFloat(), wrap1Position)
         assertEquals(0f, wrap2Position)
     }
 
@@ -147,7 +146,7 @@
     @Test
     fun callbackCalledForChildWhenParentMoved() {
         var position by mutableStateOf(0.ipx)
-        var childGlobalPosition = PxPosition(0f, 0f)
+        var childGlobalPosition = Offset(0f, 0f)
         var latch = CountDownLatch(1)
         rule.runOnUiThreadIR {
             activity.setContent {
@@ -184,7 +183,7 @@
         }
 
         assertTrue(latch.await(1, TimeUnit.SECONDS))
-        assertEquals(PxPosition(10f, 0f), childGlobalPosition)
+        assertEquals(Offset(10f, 0f), childGlobalPosition)
     }
 
     @Test
@@ -258,14 +257,14 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         rule.runOnUiThread {
-            assertEquals(PxPosition(5f, 5f), coordinates!!.positionInParent)
+            assertEquals(Offset(5f, 5f), coordinates!!.positionInParent)
 
             var root = coordinates!!
             while (root.parentCoordinates != null) {
                 root = root.parentCoordinates!!
             }
 
-            assertEquals(PxPosition.Origin, root.positionInParent)
+            assertEquals(Offset.Zero, root.positionInParent)
         }
     }
 
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OpacityTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OpacityTest.kt
index 7ac8d3b..0378a4a 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OpacityTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/OpacityTest.kt
@@ -24,7 +24,6 @@
 import androidx.compose.setValue
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.drawBehind
@@ -48,8 +47,9 @@
 @RunWith(JUnit4::class)
 class OpacityTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
     private lateinit var drawLatch: CountDownLatch
     private val unlatch = Modifier.drawBehind { drawLatch.countDown() }
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ParentDataModifierTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ParentDataModifierTest.kt
index d505357..b41ee6c 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ParentDataModifierTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/ParentDataModifierTest.kt
@@ -18,7 +18,6 @@
 import androidx.compose.Composable
 import androidx.compose.emptyContent
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutTagParentData
 import androidx.ui.core.Modifier
@@ -43,8 +42,9 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class ParentDataModifierTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     private lateinit var activity: TestActivity
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RootNodeLayoutTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RootNodeLayoutTest.kt
index 5e5ca89..1d2e46d 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RootNodeLayoutTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RootNodeLayoutTest.kt
@@ -20,7 +20,6 @@
 import android.widget.FrameLayout
 import androidx.compose.Recomposer
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutCoordinates
@@ -48,8 +47,9 @@
 @RunWith(JUnit4::class)
 class RootNodeLayoutTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
 
     @Before
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
index 4acf3dd..d443970 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.IntrinsicMeasurable
 import androidx.ui.core.IntrinsicMeasureScope
@@ -44,7 +43,7 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import org.junit.Assert
@@ -61,14 +60,16 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class RtlLayoutTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<androidx.ui.framework.test.TestActivity>(
+    val activityTestRule =
+        androidx.test.rule.ActivityTestRule<androidx.ui.framework.test.TestActivity>(
         androidx.ui.framework.test.TestActivity::class.java
     )
     private lateinit var activity: androidx.ui.framework.test.TestActivity
     internal lateinit var density: Density
     internal lateinit var countDownLatch: CountDownLatch
-    internal lateinit var position: Array<Ref<PxPosition>>
+    internal lateinit var position: Array<Ref<Offset>>
     private val size = 100.ipx
 
     @Before
@@ -76,7 +77,7 @@
         activity = activityTestRule.activity
         density = Density(activity)
         activity.hasFocusLatch.await(5, TimeUnit.SECONDS)
-        position = Array(3) { Ref<PxPosition>() }
+        position = Array(3) { Ref<Offset>() }
         countDownLatch = CountDownLatch(3)
     }
 
@@ -89,10 +90,13 @@
         }
 
         countDownLatch.await(1, TimeUnit.SECONDS)
-        Assert.assertEquals(PxPosition(0.ipx, 0.ipx), position[0].value)
-        Assert.assertEquals(PxPosition(size, size), position[1].value)
+        Assert.assertEquals(Offset(0f, 0f), position[0].value)
+        Assert.assertEquals(Offset(size.value.toFloat(), size.value.toFloat()), position[1].value)
         Assert.assertEquals(
-            PxPosition(size * 2, size * 2),
+            Offset(
+                (size * 2).value.toFloat(),
+                (size * 2).value.toFloat()
+            ),
             position[2].value
         )
     }
@@ -106,10 +110,22 @@
         }
 
         countDownLatch.await(1, TimeUnit.SECONDS)
-        Assert.assertEquals(PxPosition(0.ipx, 0.ipx), position[0].value)
-        Assert.assertEquals(PxPosition(size, size), position[1].value)
         Assert.assertEquals(
-            PxPosition(size * 2, size * 2),
+            Offset(0f, 0f),
+            position[0].value
+        )
+        Assert.assertEquals(
+            Offset(
+                size.value.toFloat(),
+                size.value.toFloat()
+            ),
+            position[1].value
+        )
+        Assert.assertEquals(
+            Offset(
+                (size * 2).value.toFloat(),
+                (size * 2).value.toFloat()
+            ),
             position[2].value
         )
     }
@@ -123,10 +139,13 @@
         }
 
         countDownLatch.await(1, TimeUnit.SECONDS)
-        Assert.assertEquals(PxPosition(0.ipx, 0.ipx), position[0].value)
-        Assert.assertEquals(PxPosition(size, size), position[1].value)
+        Assert.assertEquals(Offset(0f, 0f), position[0].value)
+        Assert.assertEquals(Offset(size.value.toFloat(), size.value.toFloat()), position[1].value)
         Assert.assertEquals(
-            PxPosition(size * 2, size * 2),
+            Offset(
+                (size * 2).value.toFloat(),
+                (size * 2).value.toFloat()
+            ),
             position[2].value
         )
     }
@@ -142,9 +161,18 @@
         countDownLatch.await(1, TimeUnit.SECONDS)
 
         countDownLatch.await(1, TimeUnit.SECONDS)
-        Assert.assertEquals(PxPosition(size * 2, 0.ipx), position[0].value)
-        Assert.assertEquals(PxPosition(size, size), position[1].value)
-        Assert.assertEquals(PxPosition(0.ipx, size * 2), position[2].value)
+        Assert.assertEquals(
+            Offset(
+                (size * 2).value.toFloat(),
+                0f
+            ),
+            position[0].value
+        )
+        Assert.assertEquals(
+            Offset(size.value.toFloat(), size.value.toFloat()),
+            position[1].value
+        )
+        Assert.assertEquals(Offset(0f, (size * 2).value.toFloat()), position[2].value)
     }
 
     @Test
@@ -332,16 +360,16 @@
             val width = placeables.fold(0.ipx) { sum, p -> sum + p.width }
             val height = placeables.fold(0.ipx) { sum, p -> sum + p.height }
             layout(width, height) {
-                var x = 0.ipx
-                var y = 0.ipx
+                var x = 0f
+                var y = 0f
                 for (placeable in placeables) {
                     if (absolutePositioning) {
-                        placeable.placeAbsolute(PxPosition(x, y))
+                        placeable.placeAbsolute(Offset(x, y))
                     } else {
-                        placeable.place(PxPosition(x, y))
+                        placeable.place(Offset(x, y))
                     }
-                    x += placeable.width
-                    y += placeable.height
+                    x += placeable.width.value.toFloat()
+                    y += placeable.height.value.toFloat()
                 }
             }
         }
@@ -403,10 +431,10 @@
 
     @Composable
     private fun saveLayoutInfo(
-        position: Ref<PxPosition>,
+        position: Ref<Offset>,
         countDownLatch: CountDownLatch
     ): Modifier = Modifier.onPositioned {
-        position.value = it.localToGlobal(PxPosition(0.ipx, 0.ipx))
+        position.value = it.localToGlobal(Offset(0f, 0f))
         countDownLatch.countDown()
     }
 }
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
index 8598aeb..1ef9e78 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
@@ -31,7 +31,6 @@
 import androidx.compose.state
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Layout
@@ -58,7 +57,7 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import org.junit.Assert.assertEquals
@@ -75,8 +74,9 @@
 @RunWith(JUnit4::class)
 class WithConstraintsTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     @get:Rule
@@ -648,7 +648,7 @@
                 ) { m, c, _ ->
                     val p = m.first().measure(c)
                     layout(0.ipx, 0.ipx) {
-                        p.place(PxPosition.Origin)
+                        p.place(Offset.Zero)
                         latch.countDown()
                     }
                 }
@@ -678,7 +678,7 @@
                 ) { m, c, _ ->
                     val p = m.first().measure(c)
                     layout(0.ipx, 0.ipx) {
-                        p.place(PxPosition.Origin)
+                        p.place(Offset.Zero)
                         latch.countDown()
                     }
                 }
@@ -776,7 +776,7 @@
                     }
                 ) { m, _, _ ->
                     layout(0.ipx, 0.ipx) {
-                        m.first().measure(Constraints(dpConstraints)).place(PxPosition.Origin)
+                        m.first().measure(Constraints(dpConstraints)).place(Offset.Zero)
                     }
                 }
             }
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WrapperTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WrapperTest.kt
index 00ec325..8325f0d 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WrapperTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/WrapperTest.kt
@@ -16,9 +16,10 @@
 package androidx.ui.core.test
 
 import android.widget.FrameLayout
+import androidx.compose.Composable
 import androidx.compose.Composition
-import androidx.compose.Recompose
 import androidx.compose.Recomposer
+import androidx.compose.invalidate
 import androidx.compose.onActive
 import androidx.compose.onCommit
 import androidx.compose.onDispose
@@ -27,7 +28,6 @@
 import androidx.lifecycle.LifecycleRegistry
 import androidx.lifecycle.ViewTreeLifecycleOwner
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.LifecycleOwnerAmbient
 import androidx.ui.core.setContent
 import androidx.ui.framework.test.TestActivity
@@ -42,11 +42,15 @@
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
 
+@Composable private fun Recompose(body: @Composable (recompose: () -> Unit) -> Unit) =
+    body(invalidate)
+
 @SmallTest
 @RunWith(JUnit4::class)
 class WrapperTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     private lateinit var activity: TestActivity
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/graphics/vector/VectorTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/graphics/vector/VectorTest.kt
index d95f0f8..4258c38 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/graphics/vector/VectorTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/graphics/vector/VectorTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.Composable
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Alignment
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
@@ -38,7 +37,6 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.toPx
 import org.junit.Assert
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
@@ -54,8 +52,9 @@
 @RunWith(JUnit4::class)
 class VectorTest {
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val rule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val rule = androidx.test.rule.ActivityTestRule<TestActivity>(TestActivity::class.java)
     private lateinit var activity: TestActivity
     private lateinit var drawLatch: CountDownLatch
 
@@ -133,7 +132,7 @@
         minimumSize: IntPx = size,
         alignment: Alignment = Alignment.Center
     ) {
-        val sizePx = size.toPx()
+        val sizePx = size.value.toFloat()
         val sizeDp = (size.value / DensityAmbient.current.density).dp
         val background = Modifier.paint(
             VectorPainter(
@@ -141,9 +140,9 @@
                 defaultHeight = sizeDp) { _, _ ->
                 Path(
                     pathData = PathData {
-                        lineTo(sizePx.value, 0.0f)
-                        lineTo(sizePx.value, sizePx.value)
-                        lineTo(0.0f, sizePx.value)
+                        lineTo(sizePx, 0.0f)
+                        lineTo(sizePx, sizePx)
+                        lineTo(0.0f, sizePx)
                         close()
                     },
                     fill = SolidColor(Color.Black)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Alignment.kt b/ui/ui-core/src/main/java/androidx/ui/core/Alignment.kt
index ecb3d4f..127caa0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Alignment.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Alignment.kt
@@ -21,8 +21,8 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.round
-import androidx.ui.unit.toPx
+import androidx.ui.unit.ipx
+import kotlin.math.roundToInt
 
 /**
  * An interface to position a point inside a 2D box. [Alignment] is often used to define
@@ -124,8 +124,8 @@
     ): IntPxPosition {
         // Convert to Px first and only round at the end, to avoid rounding twice while calculating
         // the new positions
-        val centerX = size.width.toPx() / 2f
-        val centerY = size.height.toPx() / 2f
+        val centerX = size.width.value.toFloat() / 2f
+        val centerY = size.height.value.toFloat() / 2f
         val resolvedHorizontalBias = if (layoutDirection == LayoutDirection.Ltr) {
             horizontalBias
         } else {
@@ -134,7 +134,7 @@
 
         val x = centerX * (1 + resolvedHorizontalBias)
         val y = centerY * (1 + verticalBias)
-        return IntPxPosition(x.round(), y.round())
+        return IntPxPosition(x.roundToInt().ipx, y.roundToInt().ipx)
     }
 
     @Immutable
@@ -142,8 +142,8 @@
         override fun align(size: IntPx): IntPx {
             // Convert to Px first and only round at the end, to avoid rounding twice while
             // calculating the new positions
-            val center = size.toPx() / 2f
-            return (center * (1 + bias)).round()
+            val center = size.value.toFloat() / 2f
+            return (center * (1 + bias)).roundToInt().ipx
         }
     }
 
@@ -152,9 +152,9 @@
         override fun align(size: IntPx, layoutDirection: LayoutDirection): IntPx {
             // Convert to Px first and only round at the end, to avoid rounding twice while
             // calculating the new positions
-            val center = size.toPx() / 2f
+            val center = size.value.toFloat() / 2f
             val resolvedBias = if (layoutDirection == LayoutDirection.Ltr) bias else -1 * bias
-            return (center * (1 + resolvedBias)).round()
+            return (center * (1 + resolvedBias)).roundToInt().ipx
         }
     }
 }
@@ -175,12 +175,12 @@
     override fun align(size: IntPxSize, layoutDirection: LayoutDirection): IntPxPosition {
         // Convert to Px first and only round at the end, to avoid rounding twice while calculating
         // the new positions
-        val centerX = size.width.toPx() / 2f
-        val centerY = size.height.toPx() / 2f
+        val centerX = size.width.value.toFloat() / 2f
+        val centerY = size.height.value.toFloat() / 2f
 
         val x = centerX * (1 + horizontalBias)
         val y = centerY * (1 + verticalBias)
-        return IntPxPosition(x.round(), y.round())
+        return IntPxPosition(x.roundToInt().ipx, y.roundToInt().ipx)
     }
 
     /**
@@ -197,8 +197,8 @@
         override fun align(size: IntPx, layoutDirection: LayoutDirection): IntPx {
             // Convert to Px first and only round at the end, to avoid rounding twice while
             // calculating the new positions
-            val center = size.toPx() / 2f
-            return (center * (1 + bias)).round()
+            val center = size.value.toFloat() / 2f
+            return (center * (1 + bias)).roundToInt().ipx
         }
     }
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Ambients.kt b/ui/ui-core/src/main/java/androidx/ui/core/Ambients.kt
index a87aed6..bc7fc60 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Ambients.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Ambients.kt
@@ -103,6 +103,7 @@
 val UriHandlerAmbient = staticAmbientOf<UriHandler>()
 
 @Composable
+@OptIn(androidx.animation.InternalAnimationApi::class)
 internal fun ProvideCommonAmbients(
     owner: Owner,
     uriHandler: UriHandler,
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/AndroidComposeView.kt b/ui/ui-core/src/main/java/androidx/ui/core/AndroidComposeView.kt
index 45dd7d2..7442d21 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/AndroidComposeView.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/AndroidComposeView.kt
@@ -19,10 +19,12 @@
 import android.annotation.TargetApi
 import android.content.Context
 import android.content.res.Configuration
+import android.graphics.Rect
 import android.os.Build
 import android.os.Handler
 import android.os.Looper
 import android.os.Parcelable
+import android.util.Log
 import android.util.SparseArray
 import android.view.KeyEvent as AndroidKeyEvent
 import android.view.MotionEvent
@@ -50,6 +52,7 @@
 import androidx.ui.autofill.unregisterCallback
 import androidx.ui.core.clipboard.AndroidClipboardManager
 import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.focus.FOCUS_TAG
 import androidx.ui.core.focus.FocusModifierImpl
 import androidx.ui.core.hapticfeedback.AndroidHapticFeedback
 import androidx.ui.core.hapticfeedback.HapticFeedback
@@ -126,8 +129,6 @@
 
     override val root = LayoutNode().also {
         it.measureBlocks = RootMeasureBlocks
-        it.layoutDirection =
-            context.applicationContext.resources.configuration.localeLayoutDirection
         it.modifier = Modifier.drawLayer() + semanticsModifier + focusModifier + keyInputModifier
     }
 
@@ -174,21 +175,35 @@
     // Used as an ambient for performing autofill.
     override val autofill: Autofill? get() = _autofill
 
-    override fun dispatchWindowFocusChanged(hasFocus: Boolean) {
-        if (hasFocus) {
-            focusModifier.focusDetailedState = Active
-            // TODO(b/152535715): propagate focus to children based on child focusability.
+    override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
+        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
+        Log.d(FOCUS_TAG, "Owner FocusChanged($gainFocus)")
+        if (gainFocus) {
+            // If the focus state is not Inactive, it indicates that the focus state is already
+            // set (possibly by dispatchWindowFocusChanged). So we don't update the state.
+            if (focusModifier.focusDetailedState == Inactive) {
+                focusModifier.focusDetailedState = Active
+                // TODO(b/152535715): propagate focus to children based on child focusability.
+            }
         } else {
-            // If this view lost focus, clear focus from the children. For now we clear focus
-            // from the children by requesting focus on the parent.
-            // TODO(b/151335411): use clearFocus() instead.
-            focusModifier.apply {
-                requestFocus()
+            // If this view lost focus, clear focus from the children.
+            with(focusModifier) {
+                focusNode?.clearFocus(forcedClear = true)
                 focusDetailedState = Inactive
             }
         }
     }
 
+    override fun dispatchWindowFocusChanged(hasFocus: Boolean) {
+        Log.d(FOCUS_TAG, "Owner WindowFocusChanged($hasFocus)")
+        // If the focus state is not Inactive, it indicates that this is not the first time that
+        // this Window got focus. So we maintain the previous focus state.
+        if (hasFocus && focusModifier.focusDetailedState == Inactive) {
+            focusModifier.focusDetailedState = Active
+            // TODO(b/152535715): propagate focus to children based on child focusability.
+        }
+    }
+
     override fun onKeyUp(keyCode: Int, event: AndroidKeyEvent): Boolean {
         val keyEvent = KeyEvent(Key(event.keyCode), KeyUp)
         return keyInputModifier.processKeyInput(keyEvent)
@@ -275,8 +290,8 @@
     }
 
     override fun addAndroidView(view: View, layoutNode: LayoutNode) {
-        androidViewsHandler.addView(view)
         androidViewsHandler.layoutNode[view] = layoutNode
+        androidViewsHandler.addView(view)
     }
 
     override fun removeAndroidView(view: View) {
@@ -295,18 +310,17 @@
         }
 
     private fun scheduleMeasureAndLayout() {
-        if (root.needsRemeasure) {
-            requestLayout()
-        } else {
-            measureAndLayoutHandler.removeMessages(0)
-            measureAndLayoutHandler.sendEmptyMessage(0)
-        }
+        measureAndLayoutHandler.removeMessages(0)
+        measureAndLayoutHandler.sendEmptyMessage(0)
     }
 
     override val measureIteration: Long get() = measureAndLayoutDelegate.measureIteration
 
     override fun measureAndLayout() {
-        measureAndLayoutDelegate.measureAndLayout()
+        val rootNodeResized = measureAndLayoutDelegate.measureAndLayout()
+        if (rootNodeResized) {
+            requestLayout()
+        }
         measureAndLayoutDelegate.dispatchOnPositionedCallbacks()
     }
 
@@ -316,14 +330,22 @@
         }
     }
 
+    override fun onRequestRelayout(layoutNode: LayoutNode) {
+        if (measureAndLayoutDelegate.requestRelayout(layoutNode)) {
+            scheduleMeasureAndLayout()
+        }
+    }
+
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         savedStateDelegate.stopWaitingForStateRestoration()
         trace("AndroidOwner:onMeasure") {
             val (minWidth, maxWidth) = convertMeasureSpec(widthMeasureSpec)
             val (minHeight, maxHeight) = convertMeasureSpec(heightMeasureSpec)
 
-            measureAndLayoutDelegate.rootConstraints =
-                Constraints(minWidth, maxWidth, minHeight, maxHeight)
+            measureAndLayoutDelegate.updateRootParams(
+                Constraints(minWidth, maxWidth, minHeight, maxHeight),
+                resources.configuration.localeLayoutDirection
+            )
             measureAndLayoutDelegate.measureAndLayout()
             setMeasuredDimension(root.width.value, root.height.value)
         }
@@ -579,7 +601,9 @@
 
     private val textInputServiceAndroid = TextInputServiceAndroid(this)
 
-    override val textInputService = textInputServiceFactory(textInputServiceAndroid)
+    override val textInputService =
+        @Suppress("DEPRECATION_ERROR")
+        textInputServiceFactory(textInputServiceAndroid)
 
     override val fontLoader: Font.ResourceLoader = AndroidFontResourceLoader(context)
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/AndroidViewsHandler.kt b/ui/ui-core/src/main/java/androidx/ui/core/AndroidViewsHandler.kt
index 7c3c6e5..5ce6d53 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/AndroidViewsHandler.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/AndroidViewsHandler.kt
@@ -22,6 +22,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewParent
+import androidx.ui.core.LayoutNode.LayoutState.NeedsRemeasure
 
 /**
  * Used by [AndroidComposeView] to handle the Android [View]s attached to its hierarchy.
@@ -73,7 +74,9 @@
         // their corresponding layout node.
         for (i in 0 until childCount) {
             val child = getChildAt(i)
-            if (child.isLayoutRequested && layoutNode[child]?.needsRemeasure == false) {
+            val node = layoutNode[child]
+            if (child.isLayoutRequested && node != null &&
+                node.layoutState != NeedsRemeasure) {
                 layoutNode[child]!!.requestRemeasure()
             }
         }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
index 2831c0a..fa83554 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
@@ -22,7 +22,7 @@
 import androidx.ui.graphics.Canvas
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 
 /**
@@ -52,7 +52,7 @@
     }
 
     override fun hitTest(
-        pointerPositionRelativeToScreen: PxPosition,
+        pointerPositionRelativeToScreen: Offset,
         hitPointerInputFilters: MutableList<PointerInputFilter>
     ): Boolean {
         if (isGlobalPointerInBounds(pointerPositionRelativeToScreen)) {
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
index f796cfa..e6a102a 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.core
 
+import androidx.ui.core.LayoutNode.LayoutState.Ready
 import androidx.ui.core.focus.ModifiedFocusNode
 import androidx.ui.core.keyinput.ModifiedKeyInputNode
 import androidx.ui.core.pointerinput.PointerInputFilter
@@ -26,7 +27,7 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 import androidx.ui.util.fastFirstOrNull
 import androidx.ui.util.fastForEach
@@ -125,7 +126,7 @@
         if (wrappedBy?.isShallowPlacing == true) return
 
         layoutNode.isPlaced = true
-        layoutNode.layout()
+        layoutNode.layoutChildren()
     }
 
     override operator fun get(line: AlignmentLine): IntPx? {
@@ -137,8 +138,9 @@
             val owner = layoutNode.requireOwner()
             layoutNode.zIndexSortedChildren.fastForEach { child ->
                 if (child.isPlaced) {
-                    require(!child.needsRemeasure) { "$child is not measured, draw requested" }
-                    require(!child.needsRelayout) { "$child is not laid out, draw requested" }
+                    require(child.layoutState == Ready) {
+                        "$child is not ready. layoutState is ${child.layoutState}"
+                    }
                     child.draw(canvas)
                 }
             }
@@ -149,7 +151,7 @@
     }
 
     override fun hitTest(
-        pointerPositionRelativeToScreen: PxPosition,
+        pointerPositionRelativeToScreen: Offset,
         hitPointerInputFilters: MutableList<PointerInputFilter>
     ): Boolean {
         if (isGlobalPointerInBounds(pointerPositionRelativeToScreen)) {
@@ -181,7 +183,7 @@
 
         private fun callHitTest(
             node: LayoutNode,
-            globalPoint: PxPosition,
+            globalPoint: Offset,
             hitPointerInputFilters: MutableList<PointerInputFilter>
         ): Boolean {
             return node.hitTest(globalPoint, hitPointerInputFilters)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayerWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayerWrapper.kt
index 1ec5dcc9..395c4ee4 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayerWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayerWrapper.kt
@@ -20,7 +20,7 @@
 import android.graphics.RectF
 import androidx.ui.graphics.Canvas
 import androidx.ui.unit.IntPxPosition
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 internal class LayerWrapper(
     wrapped: LayoutNodeWrapper,
@@ -80,7 +80,7 @@
         return layer
     }
 
-    override fun fromParentPosition(position: PxPosition): PxPosition {
+    override fun fromParentPosition(position: Offset): Offset {
         val matrix = layer.getMatrix()
         val targetPosition =
             if (!matrix.isIdentity) {
@@ -93,7 +93,7 @@
         return super.fromParentPosition(targetPosition)
     }
 
-    override fun toParentPosition(position: PxPosition): PxPosition {
+    override fun toParentPosition(position: Offset): Offset {
         val matrix = layer.getMatrix()
         val targetPosition =
             if (!matrix.isIdentity) {
@@ -105,10 +105,10 @@
     }
 
     /**
-     * Return a transformed [PxPosition] based off of the provided matrix transformation
+     * Return a transformed [Offset] based off of the provided matrix transformation
      * and untransformed position.
      */
-    private fun mapPointsFromMatrix(matrix: Matrix, position: PxPosition): PxPosition {
+    private fun mapPointsFromMatrix(matrix: Matrix, position: Offset): Offset {
         val x = position.x
         val y = position.y
         val cache = positionCache
@@ -120,7 +120,7 @@
             floatArrayOf(x, y).also { positionCache = it }
         }
         matrix.mapPoints(point)
-        return PxPosition(point[0], point[1])
+        return Offset(point[0], point[1])
     }
 
     override fun rectInParent(bounds: RectF) {
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
index f20f4b2..d48084e 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
@@ -28,6 +28,7 @@
 import androidx.compose.currentComposer
 import androidx.compose.onDispose
 import androidx.compose.remember
+import androidx.ui.core.LayoutNode.LayoutState
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
@@ -37,6 +38,8 @@
 import androidx.ui.unit.max
 import androidx.ui.unit.min
 import androidx.ui.util.fastForEach
+import androidx.ui.util.fastMap
+import androidx.ui.util.fastMaxBy
 
 /**
  * [Layout] is the main core component for layout. It can be used to measure and position
@@ -196,9 +199,9 @@
 ) {
     val measureBlocks = remember {
         val measureBlock: MeasureBlock = { measurables, constraints, _ ->
-            val placeables = measurables.map { it.measure(constraints) }
-            val width = placeables.maxBy { it.width }?.width ?: constraints.minWidth
-            val height = placeables.maxBy { it.height }?.height ?: constraints.minHeight
+            val placeables = measurables.fastMap { it.measure(constraints) }
+            val width = placeables.fastMaxBy { it.width }?.width ?: constraints.minWidth
+            val height = placeables.fastMaxBy { it.height }?.height ?: constraints.minHeight
             layout(width, height) {
                 placeables.fastForEach { it.place(IntPx.Zero, IntPx.Zero) }
             }
@@ -219,9 +222,10 @@
  * Used to return a fixed sized item for intrinsics measurements in [Layout]
  */
 private class DummyPlaceable(width: IntPx, height: IntPx) : Placeable() {
+    init {
+        measuredSize = IntPxSize(width, height)
+    }
     override fun get(line: AlignmentLine): IntPx? = null
-    override val measurementConstraints = Constraints()
-    override val measuredSize = IntPxSize(width, height)
     override fun place(position: IntPxPosition) { }
 }
 
@@ -479,7 +483,7 @@
     // if owner is null this means we are not yet attached. once attached the remeasuring
     // will be scheduled which would cause subcomposition
     val layoutNode = state.nodeRef.value!!
-    if (!layoutNode.needsRemeasure && layoutNode.owner != null) {
+    if (layoutNode.layoutState == LayoutState.Ready && layoutNode.owner != null) {
         state.subcompose()
     }
     onDispose {
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutCoordinates.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutCoordinates.kt
index 1a44ca0..e760bc0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutCoordinates.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutCoordinates.kt
@@ -18,8 +18,8 @@
 
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
 
 /**
  * A holder of the measured bounds for the layout (MeasureBox).
@@ -49,22 +49,22 @@
     /**
      * Converts a global position into a local position within this layout.
      */
-    fun globalToLocal(global: PxPosition): PxPosition
+    fun globalToLocal(global: Offset): Offset
 
     /**
      * Converts a local position within this layout into a global one.
      */
-    fun localToGlobal(local: PxPosition): PxPosition
+    fun localToGlobal(local: Offset): Offset
 
     /**
      * Converts a local position within this layout into an offset from the root composable.
      */
-    fun localToRoot(local: PxPosition): PxPosition
+    fun localToRoot(local: Offset): Offset
 
     /**
      * Converts a child layout position into a local position within this layout.
      */
-    fun childToLocal(child: LayoutCoordinates, childLocal: PxPosition): PxPosition
+    fun childToLocal(child: LayoutCoordinates, childLocal: Offset): Offset
 
     /**
      * Returns the child bounding box, discarding clipped rectangles, in local coordinates.
@@ -81,12 +81,12 @@
 /**
  * The global position of this layout.
  */
-inline val LayoutCoordinates.globalPosition: PxPosition get() = localToGlobal(PxPosition.Origin)
+inline val LayoutCoordinates.globalPosition: Offset get() = localToGlobal(Offset.Zero)
 
 /**
  * The position of this layout inside the root composable.
  */
-inline val LayoutCoordinates.positionInRoot: PxPosition get() = localToRoot(PxPosition.Origin)
+inline val LayoutCoordinates.positionInRoot: Offset get() = localToRoot(Offset.Zero)
 
 /**
  * The boundaries of this layout inside the root composable.
@@ -100,8 +100,8 @@
  * Returns the position of the top-left in the parent's content area or (0, 0)
  * for the root.
  */
-val LayoutCoordinates.positionInParent: PxPosition
-    get() = parentCoordinates?.childToLocal(this, PxPosition.Origin) ?: PxPosition.Origin
+val LayoutCoordinates.positionInParent: Offset
+    get() = parentCoordinates?.childToLocal(this, Offset.Zero) ?: Offset.Zero
 
 /**
  * Returns the bounding box of the child in the parent's content area, including any clipping
@@ -118,7 +118,7 @@
 val LayoutCoordinates.globalBounds: PxBounds
     get() {
         val root = findRoot(this)
-        val rootPosition = root.localToGlobal(PxPosition.Origin)
+        val rootPosition = root.localToGlobal(Offset.Zero)
         val bounds = root.childBoundingBox(this)
         return PxBounds(
             left = bounds.left + rootPosition.x,
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
index 60eb358..4f4e9db 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutModifier.kt
@@ -242,9 +242,10 @@
     ) : MeasureScope(), Density by density
 
     private class DummyPlaceable(width: IntPx, height: IntPx) : Placeable() {
+        init {
+            measuredSize = IntPxSize(width, height)
+        }
         override fun get(line: AlignmentLine): IntPx? = null
-        override val measurementConstraints = Constraints()
-        override val measuredSize = IntPxSize(width, height)
         override fun place(position: IntPxPosition) { }
     }
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNode.kt
index bcb2b78..a5ad8f4 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNode.kt
@@ -15,6 +15,10 @@
  */
 package androidx.ui.core
 
+import androidx.ui.core.LayoutNode.LayoutState.Measuring
+import androidx.ui.core.LayoutNode.LayoutState.NeedsRelayout
+import androidx.ui.core.LayoutNode.LayoutState.NeedsRemeasure
+import androidx.ui.core.LayoutNode.LayoutState.Ready
 import androidx.ui.core.focus.FocusModifierImpl
 import androidx.ui.core.focus.ModifiedFocusNode
 import androidx.ui.core.keyinput.KeyInputModifier
@@ -31,10 +35,10 @@
 import androidx.ui.graphics.drawscope.drawCanvas
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.px
-import androidx.ui.unit.round
+import androidx.ui.geometry.Offset
+import androidx.ui.unit.ipx
 import androidx.ui.util.fastForEach
+import kotlin.math.roundToInt
 import kotlin.math.sign
 
 /**
@@ -79,6 +83,15 @@
     var depth: Int = 0
 
     /**
+     * The layout state the node is currently in.
+     */
+    var layoutState = Ready
+        internal set
+
+    internal val wasMeasuredDuringThisIteration: Boolean
+        get() = requireOwner().measureIteration == outerMeasurablePlaceable.measureIteration
+
+    /**
      * Inserts a child [LayoutNode] at a particular index. If this LayoutNode [owner] is not `null`
      * then [instance] will become [attach]ed also. [instance] must have a `null` [parent].
      */
@@ -93,7 +106,7 @@
         instance.parent = this
         _children.add(index, instance)
 
-        instance.layoutNodeWrapper.wrappedBy = innerLayoutNodeWrapper
+        instance.outerLayoutNodeWrapper.wrappedBy = innerLayoutNodeWrapper
 
         val owner = this.owner
         if (owner != null) {
@@ -167,7 +180,8 @@
         }
 
         requestRemeasure()
-        layoutNodeWrapper.attach()
+        parent?.requestRemeasure()
+        outerLayoutNodeWrapper.attach()
         onAttach?.invoke(owner)
     }
 
@@ -184,8 +198,9 @@
             parentLayoutNode.requestRemeasure()
         }
         alignmentLinesQueryOwner = null
+        alignmentUsageByParent = UsageByParent.NotUsed
         onDetach?.invoke(owner)
-        layoutNodeWrapper.detach()
+        outerLayoutNodeWrapper.detach()
 
         if (outerSemantics != null) {
             owner.onSemanticsChange()
@@ -349,14 +364,9 @@
     }
 
     /**
-     * The constraints used the last time [layout] was called.
-     */
-    var constraints: Constraints = Constraints.fixed(IntPx.Zero, IntPx.Zero)
-
-    /**
      * The layout direction of the layout node.
      */
-    var layoutDirection: LayoutDirection = LayoutDirection.Ltr
+    internal var layoutDirection: LayoutDirection = LayoutDirection.Ltr
 
     /**
      * Implementation oddity around composition; used to capture a reference to this
@@ -371,12 +381,12 @@
     /**
      * The measured width of this layout and all of its [modifier]s. Shortcut for `size.width`.
      */
-    val width: IntPx get() = layoutNodeWrapper.width
+    val width: IntPx get() = outerMeasurablePlaceable.width
 
     /**
      * The measured height of this layout and all of its [modifier]s. Shortcut for `size.height`.
      */
-    val height: IntPx get() = layoutNodeWrapper.height
+    val height: IntPx get() = outerMeasurablePlaceable.height
 
     /**
      * The alignment lines of this layout, inherited + intrinsic
@@ -397,22 +407,9 @@
         internal set
 
     /**
-     * `true` when the parent's size depends on this LayoutNode's size
+     * Remembers how the node was measured by the parent.
      */
-    var affectsParentSize: Boolean = true
-        private set
-
-    /**
-     * `true` when inside [measure]
-     */
-    var isMeasuring: Boolean = false
-        private set
-
-    /**
-     * `true` when inside [layout]
-     */
-    var isLayingOut: Boolean = false
-        private set
+    internal var measuredByParent: UsageByParent = UsageByParent.NotUsed
 
     /**
      * `true` while doing [calculateAlignmentLines]
@@ -423,39 +420,14 @@
      * `true` when the current node is positioned during the measure pass,
      * since it needs to compute alignment lines.
      */
-    var positionedDuringMeasurePass: Boolean = false
-
-    /**
-     * `true` when the layout has been dirtied by [requestRemeasure]. `false` after
-     * the measurement has been complete ([place] has been called).
-     */
-    var needsRemeasure = false
-        internal set(value) {
-            require(!isMeasuring)
-            field = value
-        }
-
-    /**
-     * `true` when the layout has been measured or dirtied because the layout
-     * lambda accessed a model that has been dirtied.
-     */
-    var needsRelayout = false
-        internal set(value) {
-            require(!isMeasuring || isCalculatingAlignmentLines)
-            require(!isLayingOut)
-            field = value
-        }
+    private var positionedDuringMeasurePass: Boolean = false
 
     /**
      * `true` when the parent reads our alignment lines
      */
-    internal var alignmentLinesRead = false
+    private var alignmentLinesRead = false
 
-    /**
-     * `true` when the alignment lines have to be recomputed because the layout has
-     * been remeasured
-     */
-    internal var dirtyAlignmentLines = true
+    private var alignmentLinesCalculatedDuringLastLayout = false
 
     /**
      * `true` when an ancestor relies on our alignment lines
@@ -467,28 +439,25 @@
      * Used by the parent to identify if the child has been queried for alignment lines since
      * last measurement.
      */
-    internal var alignmentLinesQueriedSinceLastLayout = false
+    private var alignmentLinesQueriedSinceLastLayout = false
 
     /**
      * The closest layout node above in the hierarchy which asked for alignment lines.
      */
     internal var alignmentLinesQueryOwner: LayoutNode? = null
-
-    /**
-     * A local version of [Owner.measureIteration] to ensure that [MeasureBlocks.measure]
-     * is not called multiple times within a measure pass.
-     */
-    internal var measureIteration = 0L
         private set
 
+    internal var alignmentUsageByParent = UsageByParent.NotUsed
+
+    private val previousAlignmentLines = mutableMapOf<AlignmentLine, IntPx>()
+
     @Deprecated("Temporary API to support ConstraintLayout prototyping.")
     var canMultiMeasure: Boolean = false
 
-    override val parentData: Any?
-        get() = layoutNodeWrapper.parentData
-
     internal val innerLayoutNodeWrapper: LayoutNodeWrapper = InnerPlaceable(this)
-    internal var layoutNodeWrapper = innerLayoutNodeWrapper
+    private val outerMeasurablePlaceable = OuterMeasurablePlaceable(this, innerLayoutNodeWrapper)
+    internal val outerLayoutNodeWrapper: LayoutNodeWrapper
+        get() = outerMeasurablePlaceable.outerWrapper
 
     /**
      * zIndex defines the drawing order of the LayoutNode. Children with larger zIndex are drawn
@@ -541,7 +510,7 @@
             field = value
 
             // Rebuild layoutNodeWrapper
-            val oldPlaceable = layoutNodeWrapper
+            val oldOuterWrapper = outerMeasurablePlaceable.outerWrapper
             if (outerSemantics != null && isAttached()) {
                 owner!!.onSemanticsChange()
             }
@@ -550,7 +519,7 @@
             onChildPositionedCallbacks.clear()
             outerZIndexModifier = null
             innerLayerWrapper = null
-            layoutNodeWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
+            val outerWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
                 var wrapper = toWrap
                 // The order in which the following blocks occur matters.  For example, the
                 // DrawModifier block should be before the LayoutModifier block so that a Modifier
@@ -599,15 +568,17 @@
                 }
                 wrapper
             }
-            layoutNodeWrapper.wrappedBy = parent?.innerLayoutNodeWrapper
+            outerWrapper.wrappedBy = parent?.innerLayoutNodeWrapper
+            outerMeasurablePlaceable.outerWrapper = outerWrapper
             // Optimize the case where the layout itself is not modified. A common reason for
             // this is if no wrapping actually occurs above because no LayoutModifiers are
             // present in the modifier chain.
-            if (oldPlaceable != layoutNodeWrapper) {
-                oldPlaceable.detach()
+            if (oldOuterWrapper != outerWrapper) {
+                oldOuterWrapper.detach()
                 requestRemeasure()
-                layoutNodeWrapper.attach()
-            } else if (!needsRemeasure && !needsRelayout && addedCallback) {
+                parent?.requestRelayout()
+                outerWrapper.attach()
+            } else if (layoutState == Ready && addedCallback) {
                 // We need to notify the callbacks of a change in position since there's
                 // a new one.
                 requestRemeasure()
@@ -648,62 +619,24 @@
      */
     private val onChildPositionedCallbacks = mutableListOf<OnChildPositionedModifier>()
 
-    override fun measure(constraints: Constraints, layoutDirection: LayoutDirection): Placeable {
-        val owner = requireOwner()
-        val iteration = owner.measureIteration
-        val parent = parent
-        @Suppress("Deprecation")
-        canMultiMeasure = canMultiMeasure ||
-                (parent != null && parent.canMultiMeasure)
-        @Suppress("Deprecation")
-        check(measureIteration != iteration || canMultiMeasure) {
-            "measure() may not be called multiple times on the same Measurable"
-        }
-        measureIteration = iteration
-        // The more idiomatic, `if (parentLayoutNode?.isMeasuring == true)` causes boxing
-        affectsParentSize = parent != null && parent.isMeasuring == true
-        if (this.constraints == constraints &&
-            layoutNodeWrapper.measureScope.layoutDirection == layoutDirection &&
-            !needsRemeasure
-        ) {
-            return layoutNodeWrapper // we're already measured to this size, don't do anything
-        }
-
-        needsRemeasure = false
-        isMeasuring = true
-        dirtyAlignmentLines = true
-        this.constraints = constraints
-        owner.observeMeasureModelReads(this) {
-            layoutNodeWrapper.measure(constraints, layoutDirection)
-        }
-        isMeasuring = false
-        needsRelayout = true
-        return layoutNodeWrapper
-    }
-
-    override fun minIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
-        layoutNodeWrapper.minIntrinsicWidth(height, layoutDirection)
-
-    override fun maxIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
-        layoutNodeWrapper.maxIntrinsicWidth(height, layoutDirection)
-
-    override fun minIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
-        layoutNodeWrapper.minIntrinsicHeight(width, layoutDirection)
-
-    override fun maxIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
-        layoutNodeWrapper.maxIntrinsicHeight(width, layoutDirection)
-
     fun place(x: IntPx, y: IntPx) {
         with(InnerPlacementScope) {
             this.parentLayoutDirection = layoutDirection
             val previousParentWidth = parentWidth
-            this.parentWidth = layoutNodeWrapper.size.width
-            layoutNodeWrapper.place(x, y)
+            this.parentWidth = outerMeasurablePlaceable.measuredWidth
+            outerMeasurablePlaceable.place(x, y)
             this.parentWidth = previousParentWidth
         }
     }
 
-    fun draw(canvas: Canvas) = layoutNodeWrapper.draw(canvas)
+    /**
+     * Place this layout node again on the same position it was placed last time
+     */
+    internal fun replace() {
+        outerMeasurablePlaceable.replace()
+    }
+
+    fun draw(canvas: Canvas) = outerLayoutNodeWrapper.draw(canvas)
 
     /**
      * Carries out a hit test on the [PointerInputModifier]s associated with this [LayoutNode] and
@@ -722,10 +655,13 @@
      * [hitPointerInputFilters].
      */
     fun hitTest(
-        pointerPositionRelativeToScreen: PxPosition,
+        pointerPositionRelativeToScreen: Offset,
         hitPointerInputFilters: MutableList<PointerInputFilter>
     ): Boolean {
-        return layoutNodeWrapper.hitTest(pointerPositionRelativeToScreen, hitPointerInputFilters)
+        return outerLayoutNodeWrapper.hitTest(
+            pointerPositionRelativeToScreen,
+            hitPointerInputFilters
+        )
     }
 
     /**
@@ -734,14 +670,18 @@
      */
     fun getAlignmentLine(line: AlignmentLine): IntPx? {
         val linePos = alignmentLines[line] ?: return null
-        var pos = PxPosition(linePos, linePos)
+        var pos = Offset(linePos.value.toFloat(), linePos.value.toFloat())
         var wrapper = innerLayoutNodeWrapper
-        while (wrapper != layoutNodeWrapper) {
+        while (wrapper != outerLayoutNodeWrapper) {
             pos = wrapper.toParentPosition(pos)
             wrapper = wrapper.wrappedBy!!
         }
         pos = wrapper.toParentPosition(pos)
-        return if (line is HorizontalAlignmentLine) pos.y.px.round() else pos.x.px.round()
+        return if (line is HorizontalAlignmentLine) {
+            pos.y.roundToInt().ipx
+        } else {
+            pos.x.roundToInt().ipx
+        }
     }
 
     /**
@@ -758,31 +698,43 @@
         }
     }
 
-    fun layout() {
-        if (needsRelayout) {
-            needsRelayout = false
-            isLayingOut = true
+    internal fun layoutChildren() {
+        if (layoutState == NeedsRelayout) {
+            onBeforeLayoutChildren()
+        }
+        // as a result of the previous operation we can figure out a child has been resized
+        // and we need to be remeasured, not relaid out
+        if (layoutState == NeedsRelayout) {
+            layoutState = LayoutState.LayingOut
             val owner = requireOwner()
+            val parent = parent
             owner.observeLayoutModelReads(this) {
                 children.fastForEach { child ->
                     child.isPlaced = false
-                    if (alignmentLinesRequired && child.dirtyAlignmentLines) {
-                        child.needsRelayout = true
+                    if (alignmentLinesRequired && child.layoutState != NeedsRelayout &&
+                        !child.alignmentLinesCalculatedDuringLastLayout) {
+                        require(child.layoutState == Ready)
+                        child.layoutState = NeedsRelayout
                     }
                     if (!child.alignmentLinesRequired) {
                         child.alignmentLinesQueryOwner = alignmentLinesQueryOwner
                     }
                     child.alignmentLinesQueriedSinceLastLayout = false
                 }
-                positionedDuringMeasurePass = parent?.isMeasuring ?: false ||
-                        parent?.positionedDuringMeasurePass ?: false
+                positionedDuringMeasurePass = parent != null &&
+                        (parent.layoutState == Measuring ||
+                                parent.positionedDuringMeasurePass)
                 innerLayoutNodeWrapper.measureResult.placeChildren(layoutDirection)
                 children.fastForEach { child ->
                     child.alignmentLinesRead = child.alignmentLinesQueriedSinceLastLayout
                 }
             }
 
-            if (alignmentLinesRequired && dirtyAlignmentLines) {
+            alignmentLinesCalculatedDuringLastLayout = false
+            if (alignmentLinesRequired) {
+                alignmentLinesCalculatedDuringLastLayout = true
+                previousAlignmentLines.clear()
+                previousAlignmentLines.putAll(alignmentLines)
                 alignmentLines.clear()
                 children.fastForEach { child ->
                     if (!child.isPlaced) return@fastForEach
@@ -800,9 +752,58 @@
                     }
                 }
                 alignmentLines += providedAlignmentLines
-                dirtyAlignmentLines = false
+                if (previousAlignmentLines != alignmentLines) {
+                    onAlignmentsChanged()
+                }
             }
-            isLayingOut = false
+            layoutState = Ready
+        }
+    }
+
+    /**
+     * The callback to be executed before running layoutChildren.
+     *
+     * There are possible cases when we run layoutChildren() on the parent node, but some of its
+     * children are not yet measured even if they are supposed to be measured in the measure
+     * block of our parent.
+     *
+     * Example:
+     * val child = Layout(...)
+     * Layout(child) { measuruables, constraints ->
+     *    val placeable = measurables.first().measure(constraints)
+     *    layout(placeable.width, placeable.height) {
+     *       placeable.place(0, 0)
+     *    }
+     * }
+     * And now some set of changes scheduled remeasure for child and relayout for parent.
+     *
+     * During the [MeasureAndLayoutDelegate.measureAndLayout] we will start with the parent as it
+     * has lower depth. Inside the layout block we will call placeable.width which is currently
+     * dirty as the child was scheduled to remeasure. This callback will ensure it never happens
+     * and pre-remeasure everything required for this layoutChildren().
+     */
+    private fun onBeforeLayoutChildren() {
+        children.fastForEach {
+            if (it.layoutState == NeedsRemeasure &&
+                it.measuredByParent == UsageByParent.InMeasureBlock
+            ) {
+                if (it.remeasure()) {
+                    requestRemeasure()
+                }
+            }
+        }
+    }
+
+    internal fun onAlignmentsChanged() {
+        val parent = parent
+        if (parent != null) {
+            if (alignmentUsageByParent == UsageByParent.InMeasureBlock &&
+                parent.layoutState != LayoutState.LayingOut
+            ) {
+                parent.requestRemeasure()
+            } else if (alignmentUsageByParent == UsageByParent.InLayoutBlock) {
+                parent.requestRelayout()
+            }
         }
     }
 
@@ -811,9 +812,31 @@
         alignmentLinesRead = true
         alignmentLinesQueryOwner = this
         alignmentLinesQueriedSinceLastLayout = true
-        if (dirtyAlignmentLines) {
-            needsRelayout = true
-            layout()
+        val newUsageByParent = when (parent?.layoutState) {
+            Measuring -> UsageByParent.InMeasureBlock
+            LayoutState.LayingOut -> UsageByParent.InLayoutBlock
+            else -> UsageByParent.NotUsed
+        }
+        val newUsageHasLowerPriority = newUsageByParent == UsageByParent.InLayoutBlock &&
+                alignmentUsageByParent == UsageByParent.InMeasureBlock
+        if (!newUsageHasLowerPriority) {
+            alignmentUsageByParent = newUsageByParent
+        }
+        if (layoutState == NeedsRelayout || !alignmentLinesCalculatedDuringLastLayout) {
+            // layoutChildren() is a state transformation from NeedsRelayout to Ready.
+            // when we are already in NeedsRelayout we need to end up with Ready, but if we are
+            // currently measuring or need remeasure this extra layoutChildren is just a side effect
+            // and we will need to restore the current state.
+            val endState = if (layoutState == Measuring || layoutState == NeedsRemeasure) {
+                layoutState
+            } else {
+                Ready
+            }
+            if (!alignmentLinesCalculatedDuringLastLayout) {
+                layoutState = NeedsRelayout
+            }
+            layoutChildren()
+            layoutState = endState
         }
         isCalculatingAlignmentLines = false
         return alignmentLines
@@ -833,6 +856,13 @@
     }
 
     /**
+     * Used to request a new layout pass from the owner.
+     */
+    fun requestRelayout() {
+        owner?.onRequestRelayout(this)
+    }
+
+    /**
      * Used to request a new draw pass from the owner.
      */
     fun onInvalidate() {
@@ -848,8 +878,8 @@
     }
 
     internal fun dispatchOnPositionedCallbacks() {
-        if (needsRelayout) {
-            return // it hasn't been properly positioned, so don't make a call
+        if (layoutState != Ready) {
+            return // it hasn't yet been properly positioned, so don't make a call
         }
         if (!isPlaced) {
             return // it hasn't been placed, so don't make a call
@@ -872,7 +902,7 @@
      */
     fun getModifierInfo(): List<ModifierInfo> {
         val infoList = mutableListOf<ModifierInfo>()
-        var wrapper = layoutNodeWrapper
+        var wrapper = outerLayoutNodeWrapper
 
         while (wrapper != innerLayoutNodeWrapper) {
             val info = if (wrapper is LayerWrapper) {
@@ -887,6 +917,32 @@
         return infoList
     }
 
+    // Delegation from Measurable to measurableAndPlaceable
+    override fun measure(constraints: Constraints, layoutDirection: LayoutDirection) =
+        outerMeasurablePlaceable.measure(constraints, layoutDirection)
+
+    /**
+     * Return true if the measured size has been changed
+     */
+    internal fun remeasure(
+        constraints: Constraints = outerMeasurablePlaceable.lastConstraints!!,
+        layoutDirection: LayoutDirection = outerMeasurablePlaceable.lastLayoutDirection!!
+    ) = outerMeasurablePlaceable.remeasure(constraints, layoutDirection)
+
+    override val parentData: Any? get() = outerMeasurablePlaceable.parentData
+
+    override fun minIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerMeasurablePlaceable.minIntrinsicWidth(height, layoutDirection)
+
+    override fun maxIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerMeasurablePlaceable.maxIntrinsicWidth(height, layoutDirection)
+
+    override fun minIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerMeasurablePlaceable.minIntrinsicHeight(width, layoutDirection)
+
+    override fun maxIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerMeasurablePlaceable.maxIntrinsicHeight(width, layoutDirection)
+
     internal companion object {
         private val ErrorMeasureBlocks = object : NoIntrinsicsMeasureBlocks(
             error = "Undefined intrinsics block and it is required"
@@ -899,6 +955,39 @@
             ) = error("Undefined measure and it is required")
         }
     }
+
+    /**
+     * Describes the current state the [LayoutNode] is in.
+     */
+    enum class LayoutState {
+        /**
+         * Request remeasure was called on the node.
+         */
+        NeedsRemeasure,
+        /**
+         * Node is currently being measured.
+         */
+        Measuring,
+        /**
+         * Request relayout was called on the node or the node was just measured and is going to
+         * layout soon (measure stage is always being followed by the layout stage).
+         */
+        NeedsRelayout,
+        /**
+         * Node is currently being laid out.
+         */
+        LayingOut,
+        /**
+         * Node is measured and laid out or not yet attached to the [Owner] (see [LayoutNode.owner]).
+         */
+        Ready
+    }
+
+    internal enum class UsageByParent {
+        InMeasureBlock,
+        InLayoutBlock,
+        NotUsed,
+    }
 }
 
 /**
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
index 0140b8a..5f855e0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
@@ -27,9 +27,11 @@
 import androidx.ui.graphics.Paint
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
+import androidx.ui.geometry.Offset
+import androidx.ui.unit.plus
+import androidx.ui.unit.minus
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.toPxPosition
+import androidx.ui.unit.toOffset
 
 /**
  * Measurable and Placeable type that has a position.
@@ -47,14 +49,9 @@
      */
     abstract val measureScope: MeasureScope
 
-    // TODO(popam): avoid allocation here
-    final override val measuredSize: IntPxSize
-        get() = IntPxSize(measureResult.width, measureResult.height)
     // Size exposed to LayoutCoordinates.
     final override val size: IntPxSize get() = measuredSize
 
-    final override var measurementConstraints = Constraints()
-
     open val invalidateLayerOnBoundsChange = true
 
     private var _measureResult: MeasureScope.MeasureResult? = null
@@ -67,6 +64,7 @@
                 findLayer()?.invalidate()
             }
             _measureResult = value
+            measuredSize = IntPxSize(measureResult.width, measureResult.height)
         }
 
     var position: IntPxPosition = IntPxPosition.Origin
@@ -80,7 +78,7 @@
     override val parentCoordinates: LayoutCoordinates?
         get() {
             check(isAttached) { ExpectAttachedLayoutCoordinates }
-            return layoutNode.layoutNodeWrapper.wrappedBy
+            return layoutNode.outerLayoutNodeWrapper.wrappedBy
         }
 
     // True when the wrapper is running its own placing block to obtain the position of the
@@ -94,7 +92,7 @@
      * Whether a pointer that is relative to the device screen is in the bounds of this
      * LayoutNodeWrapper.
      */
-    fun isGlobalPointerInBounds(globalPointerPosition: PxPosition): Boolean {
+    fun isGlobalPointerInBounds(globalPointerPosition: Offset): Boolean {
         // TODO(shepshapard): Right now globalToLocal has to traverse the tree all the way back up
         //  so calling this is expensive.  Would be nice to cache data such that this is cheap.
         val localPointerPosition = globalToLocal(globalPointerPosition)
@@ -148,11 +146,11 @@
      * [hitPointerInputFilters].
      */
     abstract fun hitTest(
-        pointerPositionRelativeToScreen: PxPosition,
+        pointerPositionRelativeToScreen: Offset,
         hitPointerInputFilters: MutableList<PointerInputFilter>
     ): Boolean
 
-    override fun childToLocal(child: LayoutCoordinates, childLocal: PxPosition): PxPosition {
+    override fun childToLocal(child: LayoutCoordinates, childLocal: Offset): Offset {
         check(isAttached) { ExpectAttachedLayoutCoordinates }
         check(child.isAttached) { "Child $child is not attached!" }
         var wrapper = child as LayoutNodeWrapper
@@ -169,19 +167,19 @@
         return position
     }
 
-    override fun globalToLocal(global: PxPosition): PxPosition {
+    override fun globalToLocal(global: Offset): Offset {
         check(isAttached) { ExpectAttachedLayoutCoordinates }
         val wrapper = wrappedBy ?: return fromParentPosition(
-            global - layoutNode.requireOwner().calculatePosition().toPxPosition()
+            global - layoutNode.requireOwner().calculatePosition().toOffset()
         )
         return fromParentPosition(wrapper.globalToLocal(global))
     }
 
-    override fun localToGlobal(local: PxPosition): PxPosition {
+    override fun localToGlobal(local: Offset): Offset {
         return localToRoot(local) + layoutNode.requireOwner().calculatePosition()
     }
 
-    override fun localToRoot(local: PxPosition): PxPosition {
+    override fun localToRoot(local: Offset): Offset {
         check(isAttached) { ExpectAttachedLayoutCoordinates }
         var wrapper: LayoutNodeWrapper? = this
         var position = local
@@ -201,16 +199,16 @@
     }
 
     /**
-     * Converts [position] in the local coordinate system to a [PxPosition] in the
+     * Converts [position] in the local coordinate system to a [Offset] in the
      * [parentCoordinates] coordinate system.
      */
-    open fun toParentPosition(position: PxPosition): PxPosition = position + this.position
+    open fun toParentPosition(position: Offset): Offset = position + this.position
 
     /**
-     * Converts [position] in the [parentCoordinates] coordinate system to a [PxPosition] in the
+     * Converts [position] in the [parentCoordinates] coordinate system to a [Offset] in the
      * local coordinate system.
      */
-    open fun fromParentPosition(position: PxPosition): PxPosition = position - this.position
+    open fun fromParentPosition(position: Offset): Offset = position - this.position
 
     protected fun drawBorder(canvas: Canvas, paint: Paint) {
         val rect = Rect(
@@ -331,7 +329,7 @@
 
         var parentLayoutNode = layoutNode.parent
         while (parentLayoutNode != null) {
-            focusParent = parentLayoutNode.layoutNodeWrapper.findLastFocusWrapper()
+            focusParent = parentLayoutNode.outerLayoutNodeWrapper.findLastFocusWrapper()
             if (focusParent != null) {
                 return focusParent
             }
@@ -354,7 +352,7 @@
 
         var parentLayoutNode = layoutNode.parent
         while (parentLayoutNode != null) {
-            keyInputParent = parentLayoutNode.layoutNodeWrapper.findLastKeyInputWrapper()
+            keyInputParent = parentLayoutNode.outerLayoutNodeWrapper.findLastKeyInputWrapper()
             if (keyInputParent != null) {
                 return keyInputParent
             }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutTreeConsistencyChecker.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutTreeConsistencyChecker.kt
index e7a8d55..ef24df8 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutTreeConsistencyChecker.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutTreeConsistencyChecker.kt
@@ -17,6 +17,7 @@
 package androidx.ui.core
 
 import android.util.Log
+import androidx.ui.core.LayoutNode.LayoutState
 import androidx.ui.util.fastForEach
 
 /**
@@ -26,7 +27,6 @@
  */
 internal class LayoutTreeConsistencyChecker(
     private val root: LayoutNode,
-    private val duringMeasureLayout: () -> Boolean,
     private val relayoutNodes: DepthSortedSet,
     private val postponedMeasureRequests: List<LayoutNode>
 ) {
@@ -52,43 +52,18 @@
     }
 
     private fun LayoutNode.consistentLayoutState(): Boolean {
-        if (this === root && needsRemeasure) {
-            return relayoutNodes.contains(this)
-        }
-        val parent = parent
-        if (parent != null && isPlaced) {
-            if (needsRelayout) {
-                if (needsRemeasure) {
-                    // needsRelayout and needRemeasure both true are not expected
-                    return false
-                }
-                if (parent.needsRelayout || parent.needsRemeasure || parent.isMeasuring) {
-                    // relayout for the node will be done during the parent relayout which
-                    // is already scheduled or will happen after the parent's measuring
-                    return true
-                }
-                // relayout is scheduled
-                return relayoutNodes.contains(this)
+        if (isPlaced) {
+            if (layoutState == LayoutState.NeedsRemeasure &&
+                postponedMeasureRequests.contains(this)
+            ) {
+                // this node is waiting to be measured by parent or if this will not happen
+                // `onRequestMeasure` will be called for all items in `postponedMeasureRequests`
+                return true
             }
-            if (needsRemeasure) {
-                if (postponedMeasureRequests.contains(this)) {
-                    // this node is waiting to be measured by parent or if this will not happen
-                    // `onRequestMeasure` will be called for all items in `postponedMeasureRequests`
-                    return true
-                }
-                if (parent.isMeasuring || parent.isLayingOut) {
-                    return parent.measureIteration != measureIteration
-                } else {
-                    if (affectsParentSize) {
-                        // node and parent both not yet laid out -> parent remeasure
-                        // should be scheduled
-                        return parent.needsRemeasure
-                    } else {
-                        // node is not affecting parent size and parent relayout(or
-                        // remeasure, as it includes relayout) is scheduled
-                        return parent.needsRelayout || parent.needsRemeasure
-                    }
-                }
+            if (layoutState == LayoutState.NeedsRemeasure ||
+                layoutState == LayoutState.NeedsRelayout) {
+                // remeasure or relayout is scheduled
+                return relayoutNodes.contains(this)
             }
         }
         return true
@@ -97,13 +72,9 @@
     private fun nodeToString(node: LayoutNode): String {
         return with(StringBuilder()) {
             append(node)
-            if (node.needsRemeasure) append("[needsRemeasure]")
-            if (node.needsRelayout) append("[needsRelayout]")
-            if (node.isMeasuring) append("[isMeasuring]")
-            if (duringMeasureLayout()) append("[#${node.measureIteration}]")
-            if (node.isLayingOut) append("[isLayingOut]")
+            append("[${node.layoutState}]")
             if (!node.isPlaced) append("[!isPlaced]")
-            if (node.affectsParentSize) append("[affectsParentSize]")
+            append("[measuredByParent=${node.measuredByParent}]")
             if (!node.consistentLayoutState()) {
                 append("[INCONSISTENT]")
             }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/MeasureAndLayoutDelegate.kt b/ui/ui-core/src/main/java/androidx/ui/core/MeasureAndLayoutDelegate.kt
index 3fc7fc7..751f105 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/MeasureAndLayoutDelegate.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/MeasureAndLayoutDelegate.kt
@@ -16,7 +16,16 @@
 
 package androidx.ui.core
 
+import androidx.ui.core.LayoutNode.LayoutState.LayingOut
+import androidx.ui.core.LayoutNode.LayoutState.Measuring
+import androidx.ui.core.LayoutNode.LayoutState.NeedsRelayout
+import androidx.ui.core.LayoutNode.LayoutState.NeedsRemeasure
+import androidx.ui.core.LayoutNode.LayoutState.Ready
+import androidx.ui.core.LayoutNode.UsageByParent.InLayoutBlock
+import androidx.ui.core.LayoutNode.UsageByParent.InMeasureBlock
+import androidx.ui.core.LayoutNode.UsageByParent.NotUsed
 import androidx.ui.unit.IntPx
+import androidx.ui.unit.ipx
 import androidx.ui.util.fastForEach
 import androidx.ui.util.trace
 
@@ -28,8 +37,6 @@
  * Use [measureAndLayout] to perform scheduled actions and [dispatchOnPositionedCallbacks] to
  * dispatch [OnPositionedModifier] callbacks for the nodes affected by the previous
  * [measureAndLayout] execution.
- *
- * @param root Root [LayoutNode]
  */
 internal class MeasureAndLayoutDelegate(private val root: LayoutNode) {
 
@@ -44,7 +51,7 @@
     private var duringMeasureLayout = false
 
     /**
-     *
+     * Dispatches on positioned callbacks.
      */
     private val onPositionedDispatcher = OnPositionedDispatcher()
 
@@ -69,22 +76,27 @@
      */
     private val postponedMeasureRequests = mutableListOf<LayoutNode>()
 
+    private var rootConstraints = Constraints.fixed(width = IntPx.Zero, height = IntPx.Zero)
+    private var rootLayoutDirection = LayoutDirection.Ltr
+
     /**
-     * The constraints used to measure the root [LayoutNode].
+     * @param constraints The constraints to measure the root [LayoutNode] with
+     * @param layoutDirection The layout direction to measure the root [LayoutNode] with
      */
-    var rootConstraints = Constraints.fixed(width = IntPx.Zero, height = IntPx.Zero)
-        set(value) {
-            if (value != field) {
-                field = value
-                requestRemeasure(root)
-            }
+    fun updateRootParams(constraints: Constraints, layoutDirection: LayoutDirection) {
+        if (rootConstraints != constraints || rootLayoutDirection != layoutDirection) {
+            require(!duringMeasureLayout)
+            rootConstraints = constraints
+            rootLayoutDirection = layoutDirection
+            root.layoutState = NeedsRemeasure
+            relayoutNodes.add(root)
         }
+    }
 
     private val consistencyChecker: LayoutTreeConsistencyChecker? =
         if (Owner.enableExtraAssertions) {
             LayoutTreeConsistencyChecker(
                 root,
-                { duringMeasureLayout },
                 relayoutNodes,
                 postponedMeasureRequests
             )
@@ -98,58 +110,31 @@
      * @return returns true if the [measureAndLayout] execution should be scheduled as a result
      * of the request.
      */
-    fun requestRemeasure(layoutNode: LayoutNode): Boolean {
-        return trace("AndroidOwner:onRequestMeasure") {
-            layoutNode.requireOwner()
-            if (layoutNode.isMeasuring) {
-                // we're already measuring it, let's swallow. example when it happens: we compose
-                // DataNode inside WithConstraints, this calls onRequestMeasure on DataNode's
-                // parent, but this parent is WithConstraints which is currently measuring.
-                return false
-            }
-            if (layoutNode.needsRemeasure) {
-                // requestMeasure has already been called for this node
-                return false
-            }
-            if (layoutNode.isLayingOut) {
-                // requestMeasure is currently laying out and it is incorrect to request remeasure
-                // now, let's postpone it.
-                layoutNode.markRemeasureRequested()
+    fun requestRemeasure(layoutNode: LayoutNode): Boolean = when (layoutNode.layoutState) {
+        Measuring, NeedsRemeasure -> {
+            // requestMeasure has already been called for this node or
+            // we're currently measuring it, let's swallow. example when it happens: we compose
+            // DataNode inside WithConstraints, this calls onRequestMeasure on DataNode's
+            // parent, but this parent is WithConstraints which is currently measuring.
+            false
+        }
+        LayingOut -> {
+            // requestMeasure is currently laying out and it is incorrect to request remeasure
+            // now, let's postpone it.
+            postponedMeasureRequests.add(layoutNode)
+            consistencyChecker?.assertConsistent()
+            false
+        }
+        NeedsRelayout, Ready -> {
+            if (duringMeasureLayout && layoutNode.wasMeasuredDuringThisIteration) {
                 postponedMeasureRequests.add(layoutNode)
-                consistencyChecker?.assertConsistent()
-                return false
-            }
-
-            // find root of layout request:
-            var layout = layoutNode
-            while (layout.affectsParentSize && layout.parent != null) {
-                val parent = layout.parent!!
-                if (parent.isMeasuring || parent.isLayingOut) {
-                    if (!layout.needsRemeasure) {
-                        layout.markRemeasureRequested()
-                        // parent is currently measuring and we set needsRemeasure to true so if
-                        // the parent didn't yet try to measure the node it will remeasure it.
-                        // if the parent didn't plan to measure during this pass then needsRemeasure
-                        // stay 'true' and we will manually call 'onRequestMeasure' for all
-                        // the not-measured nodes in 'postponedMeasureRequests'.
-                        postponedMeasureRequests.add(layout)
-                    }
-                    consistencyChecker?.assertConsistent()
-                    return false
-                } else {
-                    layout.markRemeasureRequested()
-                    if (parent.needsRemeasure) {
-                        // don't need to do anything else since the parent is already scheduled
-                        // for a remeasuring
-                        consistencyChecker?.assertConsistent()
-                        return false
-                    }
-                    layout = parent
+            } else {
+                layoutNode.layoutState = NeedsRemeasure
+                if (layoutNode.isPlaced || layoutNode.canAffectPlacedParent) {
+                    relayoutNodes.add(layoutNode)
                 }
             }
-            layout.markRemeasureRequested()
-
-            requestRelayout(layout.parent ?: layout)
+            !duringMeasureLayout
         }
     }
 
@@ -159,105 +144,93 @@
      * @return returns true if the [measureAndLayout] execution should be scheduled as a result
      * of the request.
      */
-    fun requestRelayout(layoutNode: LayoutNode): Boolean {
-        if (layoutNode.needsRelayout || (layoutNode.needsRemeasure && layoutNode !== root) ||
-            layoutNode.isLayingOut || layoutNode.isMeasuring
-        ) {
+    fun requestRelayout(layoutNode: LayoutNode): Boolean = when (layoutNode.layoutState) {
+        Measuring, NeedsRemeasure, NeedsRelayout, LayingOut -> {
             // don't need to do anything else since the parent is already scheduled
             // for a relayout (measure will trigger relayout), or is laying out right now
             consistencyChecker?.assertConsistent()
-            return false
+            false
         }
-        layoutNode.requireOwner()
-        var nodeToRelayout = layoutNode
-
-        // mark alignments as dirty first
-        if (!layoutNode.alignmentLinesRequired) {
-            // Mark parents alignment lines as dirty, for cases when we needed alignment lines
-            // at some point, but currently they are not queried anymore. If they are actively
-            // queried, they will be made dirty below in this method.
-            var layout: LayoutNode? = layoutNode
-            while (layout != null && !layout.dirtyAlignmentLines) {
-                layout.dirtyAlignmentLines = true
-                layout = layout.parent
+        Ready -> {
+            layoutNode.layoutState = NeedsRelayout
+            if (layoutNode.isPlaced) {
+                relayoutNodes.add(layoutNode)
             }
+            !duringMeasureLayout
+        }
+    }
+
+    private fun doRemeasure(layoutNode: LayoutNode): Boolean {
+        val sizeChanged = if (layoutNode === root) {
+            layoutNode.remeasure(rootConstraints, rootLayoutDirection)
         } else {
-            var layout = layoutNode
-            while (layout != layoutNode.alignmentLinesQueryOwner &&
-                // and relayout or remeasure(includes relayout) is not scheduled already
-                !(layout.needsRelayout || layout.needsRemeasure || layoutNode.isLayingOut ||
-                        layoutNode.isMeasuring)
-            ) {
-                layout.markRelayoutRequested()
-                layout.dirtyAlignmentLines = true
-                val parent = layout.parent
-                if (parent == null) break
-                layout = parent
+            layoutNode.remeasure()
+        }
+        val parent = layoutNode.parent
+        if (sizeChanged) {
+            if (parent == null) {
+                return true
+            } else if (layoutNode.measuredByParent == InMeasureBlock) {
+                requestRemeasure(parent)
+            } else {
+                require(layoutNode.measuredByParent == InLayoutBlock)
+                requestRelayout(parent)
             }
-            layout.dirtyAlignmentLines = true
-            nodeToRelayout = layout
         }
-
-        nodeToRelayout.markRelayoutRequested()
-        relayoutNodes.add(nodeToRelayout)
-        consistencyChecker?.assertConsistent()
-        return !duringMeasureLayout
-    }
-
-    private fun LayoutNode.markRemeasureRequested() {
-        needsRemeasure = true
-        if (needsRelayout) {
-            // cancel needsRelayout as remeasure includes relayout
-            needsRelayout = false
-        }
-    }
-
-    private fun LayoutNode.markRelayoutRequested() {
-        // remeasure includes relayout so we are ok
-        if (!needsRemeasure) {
-            needsRelayout = true
-        }
+        return false
     }
 
     /**
      * Iterates through all LayoutNodes that have requested layout and measures and lays them out
      */
-    fun measureAndLayout() {
+    fun measureAndLayout(): Boolean {
+        require(!duringMeasureLayout)
+        // we don't need to measure any children unless we have the correct root constraints
+        if (rootConstraints.isZero) {
+            return false
+        }
+        var rootNodeResized = false
         trace("AndroidOwner:measureAndLayout") {
             if (relayoutNodes.isNotEmpty()) {
                 duringMeasureLayout = true
                 relayoutNodes.popEach { layoutNode ->
-                    measureIteration++
-                    if (layoutNode === root) {
-                        // it is the root node - the only top node from relayoutNodes
-                        // which needs to be remeasured.
-                        layoutNode.measure(rootConstraints, layoutNode.layoutDirection)
-                    }
-                    require(!layoutNode.needsRemeasure) {
-                        "$layoutNode shouldn't require remeasure. relayoutNodes " +
-                                "consists of the top nodes of the affected subtrees"
-                    }
-                    if (layoutNode.needsRelayout) {
-                        layoutNode.layout()
-                        onPositionedDispatcher.onNodePositioned(layoutNode)
-                        consistencyChecker?.assertConsistent()
-                    }
-                    // execute postponed `onRequestMeasure`
-                    if (postponedMeasureRequests.isNotEmpty()) {
-                        postponedMeasureRequests.fastForEach {
-                            // if it was detached or already measured by the parent then skip it
-                            if (it.isAttached() && it.needsRemeasure) {
-                                it.needsRemeasure = false
-                                requestRemeasure(it)
+                    val alignmentLinesOwner = layoutNode.alignmentLinesQueryOwner
+                    if (layoutNode.isPlaced ||
+                        layoutNode.canAffectPlacedParent ||
+                        (alignmentLinesOwner != null && alignmentLinesOwner
+                            .alignmentUsageByParent != NotUsed)
+                    ) {
+                        if (layoutNode.layoutState == NeedsRemeasure) {
+                            if (doRemeasure(layoutNode)) {
+                                rootNodeResized = true
                             }
                         }
-                        postponedMeasureRequests.clear()
+                        if (layoutNode.layoutState == NeedsRelayout && layoutNode.isPlaced) {
+                            if (layoutNode === root) {
+                                layoutNode.place(0.ipx, 0.ipx)
+                            } else {
+                                layoutNode.replace()
+                            }
+                            onPositionedDispatcher.onNodePositioned(layoutNode)
+                            consistencyChecker?.assertConsistent()
+                        }
+                        measureIteration++
+                        // execute postponed `onRequestMeasure`
+                        if (postponedMeasureRequests.isNotEmpty()) {
+                            postponedMeasureRequests.fastForEach {
+                                if (it.isAttached()) {
+                                    requestRemeasure(it)
+                                }
+                            }
+                            postponedMeasureRequests.clear()
+                        }
                     }
                 }
                 duringMeasureLayout = false
                 consistencyChecker?.assertConsistent()
             }
         }
+        return rootNodeResized
     }
 
     /**
@@ -275,4 +248,8 @@
     fun onNodeDetached(node: LayoutNode) {
         relayoutNodes.remove(node)
     }
+
+    private val LayoutNode.canAffectPlacedParent
+        get() = layoutState == NeedsRemeasure && parent?.isPlaced == true &&
+                (measuredByParent == InMeasureBlock || alignmentLinesQueryOwner != null)
 }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Measured.kt b/ui/ui-core/src/main/java/androidx/ui/core/Measured.kt
index ed32d2c..dcbae4e 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Measured.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Measured.kt
@@ -21,7 +21,7 @@
 /**
  * Read-only wrapper over [Placeable] that exposes the measurement result with no placing ability.
  */
-/*inline*/ class Measured(internal val placeable: Placeable) {
+inline class Measured(internal val placeable: Placeable) {
     /**
      * The measured width of the layout.
      */
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/OuterMeasurablePlaceable.kt b/ui/ui-core/src/main/java/androidx/ui/core/OuterMeasurablePlaceable.kt
new file mode 100644
index 0000000..a860a75
--- /dev/null
+++ b/ui/ui-core/src/main/java/androidx/ui/core/OuterMeasurablePlaceable.kt
@@ -0,0 +1,138 @@
+/*
+ * 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.core
+
+import androidx.ui.core.LayoutNode.LayoutState
+import androidx.ui.core.LayoutNode.MeasureBlocks
+import androidx.ui.core.LayoutNode.UsageByParent
+import androidx.ui.unit.IntPx
+import androidx.ui.unit.IntPxPosition
+import androidx.ui.unit.IntPxSize
+
+internal class OuterMeasurablePlaceable(
+    private val layoutNode: LayoutNode,
+    var outerWrapper: LayoutNodeWrapper
+) : Measurable, Placeable() {
+
+    private var measuredOnce = false
+    val lastConstraints: Constraints? get() = if (measuredOnce) measurementConstraints else null
+    var lastLayoutDirection: LayoutDirection? = null
+        private set
+    var lastPosition: IntPxPosition? = null
+        private set
+    private val lastProvidedAlignmentLines = mutableMapOf<AlignmentLine, IntPx>()
+
+    /**
+     * A local version of [Owner.measureIteration] to ensure that [MeasureBlocks.measure]
+     * is not called multiple times within a measure pass.
+     */
+    var measureIteration = -1L
+        private set
+
+    override val parentData: Any? get() = outerWrapper.parentData
+
+    /**
+     * The function to be executed when the parent layout measures its children.
+     */
+    override fun measure(constraints: Constraints, layoutDirection: LayoutDirection): Placeable {
+        // when we measure the root it is like the virtual parent is currently laying out
+        val parentState = layoutNode.parent?.layoutState ?: LayoutState.LayingOut
+        layoutNode.measuredByParent = when (parentState) {
+            LayoutState.Measuring -> UsageByParent.InMeasureBlock
+            LayoutState.LayingOut -> UsageByParent.InLayoutBlock
+            else -> throw IllegalStateException(
+                "Measurable could be only measured from the parent's measure or layout block." +
+                        "Parents state is $parentState"
+            )
+        }
+        remeasure(constraints, layoutDirection)
+        return this
+    }
+
+    /**
+     * Return true if the measured size has been changed
+     */
+    fun remeasure(constraints: Constraints, layoutDirection: LayoutDirection): Boolean {
+        val owner = layoutNode.requireOwner()
+        val iteration = owner.measureIteration
+        val parent = layoutNode.parent
+        @Suppress("Deprecation")
+        layoutNode.canMultiMeasure = layoutNode.canMultiMeasure ||
+                (parent != null && parent.canMultiMeasure)
+        @Suppress("Deprecation")
+        check(measureIteration != iteration || layoutNode.canMultiMeasure) {
+            "measure() may not be called multiple times on the same Measurable"
+        }
+        measureIteration = owner.measureIteration
+        if (layoutNode.layoutState == LayoutState.NeedsRemeasure ||
+            measurementConstraints != constraints ||
+            lastLayoutDirection != layoutDirection
+        ) {
+            measuredOnce = true
+            layoutNode.layoutState = LayoutState.Measuring
+            measurementConstraints = constraints
+            lastLayoutDirection = layoutDirection
+            lastProvidedAlignmentLines.clear()
+            lastProvidedAlignmentLines.putAll(layoutNode.providedAlignmentLines)
+            owner.observeMeasureModelReads(layoutNode) {
+                outerWrapper.measure(constraints, layoutDirection)
+            }
+            layoutNode.layoutState = LayoutState.NeedsRelayout
+            if (layoutNode.providedAlignmentLines != lastProvidedAlignmentLines) {
+                layoutNode.onAlignmentsChanged()
+            }
+            val previousSize = measuredSize
+            val newWidth = outerWrapper.width
+            val newHeight = outerWrapper.height
+            if (newWidth != previousSize.width ||
+                newHeight != previousSize.height
+            ) {
+                measuredSize = IntPxSize(newWidth, newHeight)
+                return true
+            }
+        }
+        return false
+    }
+
+    override fun get(line: AlignmentLine): IntPx? = outerWrapper[line]
+
+    override fun place(position: IntPxPosition) {
+        lastPosition = position
+        with(InnerPlacementScope) {
+            outerWrapper.placeAbsolute(position)
+        }
+    }
+
+    /**
+     * Calls [place] with the same position used during the last [place] call
+     */
+    fun replace() {
+        place(checkNotNull(lastPosition))
+    }
+
+    override fun minIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerWrapper.minIntrinsicWidth(height, layoutDirection)
+
+    override fun maxIntrinsicWidth(height: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerWrapper.maxIntrinsicWidth(height, layoutDirection)
+
+    override fun minIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerWrapper.minIntrinsicHeight(width, layoutDirection)
+
+    override fun maxIntrinsicHeight(width: IntPx, layoutDirection: LayoutDirection): IntPx =
+        outerWrapper.maxIntrinsicHeight(width, layoutDirection)
+}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Owner.kt b/ui/ui-core/src/main/java/androidx/ui/core/Owner.kt
index 7164ae7..d859895 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Owner.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Owner.kt
@@ -111,6 +111,11 @@
     fun onRequestMeasure(layoutNode: LayoutNode)
 
     /**
+     * Called by [LayoutNode] to request the Owner a new measurement+layout.
+     */
+    fun onRequestRelayout(layoutNode: LayoutNode)
+
+    /**
      * Called by [LayoutNode] when it is attached to the view system and now has an owner.
      * This is used by [Owner] to track which nodes are associated with it. It will only be
      * called when [node] is not already attached to an owner.
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Placeable.kt b/ui/ui-core/src/main/java/androidx/ui/core/Placeable.kt
index 06c12a5..e4666bc 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Placeable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Placeable.kt
@@ -19,8 +19,9 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.coerceIn
+import androidx.ui.unit.ipx
 import androidx.ui.unit.round
 
 /**
@@ -36,10 +37,8 @@
      * not respect its incoming constraints, so the width will be coerced inside the min and
      * max width.
      */
-    val width: IntPx get() = measuredSize.width.coerceIn(
-        measurementConstraints.minWidth,
-        measurementConstraints.maxWidth
-    )
+    var width: IntPx = 0.ipx
+        private set
 
     /**
      * The height, in pixels, of the measured layout, as seen by the parent. This is usually the
@@ -47,10 +46,8 @@
      * not respect its incoming constraints, so the height will be coerced inside the min and
      * max height.
      */
-    val height: IntPx get() = measuredSize.height.coerceIn(
-        measurementConstraints.minHeight,
-        measurementConstraints.maxHeight
-    )
+    var height: IntPx = 0.ipx
+        private set
 
     /**
      * Returns the position of an [alignment line][AlignmentLine],
@@ -61,7 +58,18 @@
     /**
      * The measured size of this Placeable. This might not respect [measurementConstraints].
      */
-    protected abstract val measuredSize: IntPxSize
+    protected var measuredSize: IntPxSize = IntPxSize.Zero
+        set(value) {
+            field = value
+            width = value.width.coerceIn(
+                measurementConstraints.minWidth,
+                measurementConstraints.maxWidth
+            )
+            height = value.height.coerceIn(
+                measurementConstraints.minHeight,
+                measurementConstraints.maxHeight
+            )
+        }
 
     internal val measuredWidth get() = measuredSize.width
 
@@ -75,7 +83,7 @@
     /**
      * The constraints used for the measurement made to obtain this [Placeable].
      */
-    protected abstract val measurementConstraints: Constraints
+    protected var measurementConstraints: Constraints = Constraints()
 
     /**
      * The offset to be added to an apparent position assigned to this [Placeable] to make it real.
@@ -133,7 +141,7 @@
          * automatic position mirroring will not happen and the [Placeable] will be placed at the
          * given [position], similar to the [placeAbsolute] method.
          */
-        fun Placeable.place(position: PxPosition) = placeAutoMirrored(position.round())
+        fun Placeable.place(position: Offset) = placeAutoMirrored(position.round())
 
         /**
          * Place a [Placeable] at [x], [y] in its parent's coordinate system.
@@ -151,7 +159,7 @@
          * Unlike [place], the given [position] will not implicitly react in RTL layout direction
          * contexts.
          */
-        fun Placeable.placeAbsolute(position: PxPosition) = placeAbsolute(position.round())
+        fun Placeable.placeAbsolute(position: Offset) = placeAbsolute(position.round())
 
         /**
          * Place a [Placeable] at [x], [y] in its parent's coordinate system.
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/PointerInput.kt b/ui/ui-core/src/main/java/androidx/ui/core/PointerInput.kt
index cbf43de..5c2994062 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/PointerInput.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/PointerInput.kt
@@ -19,7 +19,7 @@
 import androidx.compose.Immutable
 import androidx.compose.Stable
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 
 /**
@@ -74,7 +74,7 @@
     @Stable
     val uptime: Uptime? = null,
     @Stable
-    val position: PxPosition? = null,
+    val position: Offset? = null,
     @Stable
     val down: Boolean = false
 )
@@ -87,7 +87,7 @@
  */
 @Immutable
 data class ConsumedData(
-    val positionChange: PxPosition = PxPosition.Origin,
+    val positionChange: Offset = Offset.Zero,
     val downChange: Boolean = false
 )
 
@@ -185,14 +185,14 @@
  * True if this [PointerInputChange] represents a pointer moving on the screen and some of that
  * movement has not been consumed.
  */
-fun PointerInputChange.positionChanged() = this.positionChangeInternal(false) != PxPosition.Origin
+fun PointerInputChange.positionChanged() = this.positionChangeInternal(false) != Offset.Zero
 
 /**
  * True if this [PointerInputChange] represents a pointer moving on the screen ignoring how much
  * of that movement may have been consumed.
  */
 fun PointerInputChange.positionChangedIgnoreConsumed() =
-    this.positionChangeInternal(true) != PxPosition.Origin
+    this.positionChangeInternal(true) != Offset.Zero
 
 /**
  * The distance that the pointer has moved on the screen minus any distance that has been consumed.
@@ -205,13 +205,13 @@
  */
 fun PointerInputChange.positionChangeIgnoreConsumed() = this.positionChangeInternal(true)
 
-private fun PointerInputChange.positionChangeInternal(ignoreConsumed: Boolean = false): PxPosition {
+private fun PointerInputChange.positionChangeInternal(ignoreConsumed: Boolean = false): Offset {
     val previousPosition = previous.position
     val currentPosition = current.position
 
     val offset =
         if (previousPosition == null || currentPosition == null) {
-            PxPosition(0.0f, 0.0f)
+            Offset(0.0f, 0.0f)
         } else {
             currentPosition - previousPosition
         }
@@ -269,7 +269,7 @@
     //  less than the total change.
     return copy(
         consumed = this.consumed.copy(
-            positionChange = PxPosition(
+            positionChange = Offset(
                 newConsumedDx,
                 newConsumedDy
             )
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/PointerInputDelegatingWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/PointerInputDelegatingWrapper.kt
index fcf84f8..ecea5cc 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/PointerInputDelegatingWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/PointerInputDelegatingWrapper.kt
@@ -18,7 +18,7 @@
 
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 internal class PointerInputDelegatingWrapper(
     wrapped: LayoutNodeWrapper,
@@ -30,7 +30,7 @@
     }
 
     override fun hitTest(
-        pointerPositionRelativeToScreen: PxPosition,
+        pointerPositionRelativeToScreen: Offset,
         hitPointerInputFilters: MutableList<PointerInputFilter>
     ): Boolean {
         if (isGlobalPointerInBounds(pointerPositionRelativeToScreen)) {
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt b/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
index b46f0f9..cfc2401 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
@@ -41,7 +41,7 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.max
 import androidx.ui.unit.round
@@ -186,7 +186,7 @@
     Layout(children = emptyContent(), modifier = Modifier.onPositioned { childCoordinates ->
         val coordinates = childCoordinates.parentCoordinates!!
         // Get the global position of the parent
-        val layoutPosition = coordinates.localToGlobal(PxPosition.Origin).round()
+        val layoutPosition = coordinates.localToGlobal(Offset.Zero).round()
         val layoutSize = coordinates.size
 
         popupLayout.popupPositionProperties.parentPosition = layoutPosition
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
index adfeaa6..4c86db0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
@@ -17,6 +17,7 @@
 
 import android.app.Activity
 import android.content.Context
+import android.os.Build
 import android.view.View
 import android.view.ViewGroup
 import android.widget.FrameLayout
@@ -27,12 +28,16 @@
 import androidx.compose.CompositionReference
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
+import androidx.compose.SlotTable
 import androidx.compose.compositionFor
+import androidx.compose.currentComposer
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleEventObserver
 import androidx.lifecycle.LifecycleOwner
 import androidx.ui.core.selection.SelectionContainer
 import androidx.ui.node.UiComposer
+import java.util.Collections
+import java.util.WeakHashMap
 
 /**
  * Composes the children of the view with the passed in [composable].
@@ -190,6 +195,10 @@
     recomposer: Recomposer,
     content: @Composable () -> Unit
 ): Composition {
+    if (inspectionWanted(owner)) {
+        owner.view.setTag(R.id.inspection_slot_table_set,
+                Collections.newSetFromMap(WeakHashMap<SlotTable, Boolean>()))
+    }
     val original = compositionFor(context, owner.root, recomposer)
     val wrapped = owner.view.getTag(R.id.wrapped_composition_tag)
             as? WrappedComposition
@@ -217,6 +226,13 @@
             }
             if (owner.savedStateRegistry != null) {
                 original.setContent {
+                    @Suppress("UNCHECKED_CAST")
+                    (owner.view.getTag(R.id.inspection_slot_table_set) as? MutableSet<SlotTable>)
+                            ?.let {
+                                val composer = currentComposer
+                                composer.collectKeySourceInformation()
+                                it.add(composer.slotTable)
+                            }
                     ProvideAndroidAmbients(owner) {
                         WrapWithSelectionContainer(content)
                     }
@@ -273,3 +289,17 @@
     ViewGroup.LayoutParams.WRAP_CONTENT,
     ViewGroup.LayoutParams.WRAP_CONTENT
 )
+
+/**
+ * Determines if inspection is wanted for the Layout Inspector.
+ *
+ * When DEBUG_VIEW_ATTRIBUTES an/or DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE is turned on for the
+ * current application the Layout Inspector is inspecting. An application cannot directly access
+ * these global settings, nor is the static field: View.sDebugViewAttributes available.
+ *
+ *
+ * Instead check if the attributeSourceResourceMap is not empty.
+ */
+private fun inspectionWanted(owner: AndroidOwner): Boolean =
+    Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
+            owner.view.attributeSourceResourceMap.isNotEmpty()
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusNodeUtils.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusNodeUtils.kt
index 121429b..7fabb64 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusNodeUtils.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusNodeUtils.kt
@@ -19,11 +19,13 @@
 import androidx.ui.core.LayoutNode
 import androidx.ui.util.fastForEach
 
+internal val FOCUS_TAG = "Compose Focus"
+
 internal fun LayoutNode.focusableChildren(): List<ModifiedFocusNode> {
     val focusableChildren = mutableListOf<ModifiedFocusNode>()
     // TODO(b/152529395): Write a test for LayoutNode.focusableChildren(). We were calling the wrong
     //  function on [LayoutNodeWrapper] but no test caught this.
-    layoutNodeWrapper.findNextFocusWrapper()?.let { focusableChildren.add(it) }
+    this.outerLayoutNodeWrapper.findNextFocusWrapper()?.let { focusableChildren.add(it) }
         ?: children.fastForEach { layout -> focusableChildren.addAll(layout.focusableChildren()) }
     return focusableChildren
 }
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
index 84230dd..b0c8dfd9 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
@@ -127,14 +127,15 @@
     /**
      * This function clears focus from this node.
      *
-     * Note: This function is private, and should only be called by a parent [ModifiedFocusNode] to
-     * clear focus from one of its child [ModifiedFocusNode]s.
+     * Note: This function should only be called by a parent [ModifiedFocusNode] to
+     * clear focus from one of its child [ModifiedFocusNode]s. It does not change the state of
+     * the parent.
      */
-    private fun clearFocus(): Boolean {
+    internal fun clearFocus(forcedClear: Boolean = false): Boolean {
         return when (modifier.focusDetailedState) {
             Active -> {
-                modifier.focusDetailedState = Inactive
                 findParentFocusNode()?.modifier?.focusedChild = null
+                modifier.focusDetailedState = Inactive
                 true
             }
             /**
@@ -142,36 +143,32 @@
              * first, before clearing focus of this node.
              */
             ActiveParent -> {
-                if (clearFocusFromChildren()) {
-                    modifier.focusDetailedState = Active
-                    clearFocus()
-                } else {
-                    false
+                val focusedChild = modifier.focusedChild
+                requireNotNull(focusedChild)
+                val success = focusedChild.clearFocus(forcedClear)
+                if (success) {
+                    findParentFocusNode()?.modifier?.focusedChild = null
+                    modifier.focusDetailedState = Inactive
                 }
+                success
             }
             /**
-             * If the node is [Captured], deny requests to clear focus.
+             * If the node is [Captured], deny requests to clear focus, except for a forced clear.
              */
-            Captured -> false
+            Captured -> {
+                if (forcedClear) {
+                    modifier.focusDetailedState = Inactive
+                    findParentFocusNode()?.modifier?.focusedChild = null
+                }
+                forcedClear
+            }
             /**
-             * Nothing to do if the node is not focused. Even though the node ends up in a
-             * cleared state, we return false to indicate that we didn't change any state (This
-             * return value is used to trigger a recomposition, so returning false will not
-             * trigger any recomposition).
+             * Nothing to do if the node is not focused.
              */
-            Inactive, Disabled -> false
+            Inactive, Disabled -> true
         }
     }
 
-    private fun clearFocusFromChildren(): Boolean {
-        require(modifier.focusDetailedState == ActiveParent)
-
-        val focusedChild = modifier.focusedChild
-        requireNotNull(focusedChild)
-
-        return focusedChild.clearFocus()
-    }
-
     /**
      * Focusable children of this [ModifiedFocusNode] can use this function to request focus.
      *
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DoubleTapGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DoubleTapGestureFilter.kt
index 7762d71..30e1b88 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DoubleTapGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DoubleTapGestureFilter.kt
@@ -33,7 +33,7 @@
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.temputils.delay
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 import kotlinx.coroutines.Job
 import kotlin.coroutines.CoroutineContext
@@ -54,7 +54,7 @@
  * Also, given that this gesture detector is so temporary, opting to not write substantial tests.
  */
 fun Modifier.doubleTapGestureFilter(
-    onDoubleTap: (PxPosition) -> Unit
+    onDoubleTap: (Offset) -> Unit
 ): Modifier = composed {
     @Suppress("DEPRECATION")
     val coroutineContext = CoroutineContextAmbient.current
@@ -68,7 +68,7 @@
     val coroutineContext: CoroutineContext
 ) : PointerInputFilter() {
 
-    lateinit var onDoubleTap: (PxPosition) -> Unit
+    lateinit var onDoubleTap: (Offset) -> Unit
 
     private enum class State {
         Idle, Down, Up, SecondDown
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragGestureFilter.kt
index c178e08..895ff60 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragGestureFilter.kt
@@ -21,7 +21,7 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.composed
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 // TODO(b/146133703): Likely rename to PanGestureDetector as per b/146133703
 /**
@@ -91,24 +91,24 @@
         enabled = true
     }
 
-    fun startDrag(downPosition: PxPosition) {
+    fun startDrag(downPosition: Offset) {
         started = true
         touchSlopDragObserver.onStart(downPosition)
     }
 
     val rawDragObserver: DragObserver =
         object : DragObserver {
-            override fun onStart(downPosition: PxPosition) {
+            override fun onStart(downPosition: Offset) {
                 if (!started) {
                     touchSlopDragObserver.onStart(downPosition)
                 }
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 return touchSlopDragObserver.onDrag(dragDistance)
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 started = false
                 enabled = false
                 touchSlopDragObserver.onStop(velocity)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
index c75d811..cd4433d 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
@@ -26,9 +26,8 @@
 import androidx.ui.core.composed
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.positionChange
-import androidx.ui.geometry.Offset
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * This gesture filter detects when the average distance change of all pointers surpasses touch
@@ -76,8 +75,8 @@
         ) {
             // Get current average change.
             val averagePositionChange = getAveragePositionChange(changes)
-            val dx = averagePositionChange.dx
-            val dy = averagePositionChange.dy
+            val dx = averagePositionChange.x
+            val dy = averagePositionChange.y
 
             // Track changes during postUp and during postDown.  This allows for fancy dragging
             // due to a parent being dragged and will likely be removed.
@@ -149,7 +148,7 @@
  * Get's the average distance change of all pointers as an Offset.
  */
 private fun getAveragePositionChange(changes: List<PointerInputChange>): Offset {
-    val sum = changes.fold(PxPosition.Origin) { sum, change ->
+    val sum = changes.fold(Offset.Zero) { sum, change ->
         sum + change.positionChange()
     }
     val sizeAsFloat = changes.size.toFloat()
@@ -163,8 +162,8 @@
  */
 private fun Offset.horizontalDirection() =
     when {
-        this.dx < 0f -> Direction.LEFT
-        this.dx > 0f -> Direction.RIGHT
+        this.x < 0f -> Direction.LEFT
+        this.x > 0f -> Direction.RIGHT
         else -> null
     }
 
@@ -173,7 +172,7 @@
  */
 private fun Offset.verticalDirection() =
     when {
-        this.dy < 0f -> Direction.UP
-        this.dy > 0f -> Direction.DOWN
+        this.y < 0f -> Direction.UP
+        this.y > 0f -> Direction.DOWN
         else -> null
     }
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressDragGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressDragGestureFilter.kt
index 74441b8..93de110 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressDragGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressDragGestureFilter.kt
@@ -25,7 +25,7 @@
 import androidx.ui.core.composed
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 interface LongPressDragObserver {
 
@@ -42,7 +42,7 @@
      * @see onDrag
      * @see onStop
      */
-    fun onLongPress(pxPosition: PxPosition) {}
+    fun onLongPress(pxPosition: Offset) {}
 
     /**
      * Override to be notified when dragging has actually begun.
@@ -76,7 +76,7 @@
      * @param dragDistance The distance that has been dragged.  Reflects the average drag distance
      * of all pointers.
      */
-    fun onDrag(dragDistance: PxPosition) = PxPosition.Origin
+    fun onDrag(dragDistance: Offset) = Offset.Zero
 
     /**
      * Override to be notified when a drag has stopped.
@@ -84,7 +84,7 @@
      * This is called once all pointers have stopped interacting with this DragGestureDetector and
      * [onLongPress] was previously called.
      */
-    fun onStop(velocity: PxPosition) {}
+    fun onStop(velocity: Offset) {}
 
     /**
      * Override to be notified when the drag has been cancelled.
@@ -141,16 +141,16 @@
 
         object : DragObserver {
 
-            override fun onStart(downPosition: PxPosition) {
+            override fun onStart(downPosition: Offset) {
                 longPressDragObserver.onDragStart()
                 dragStarted = true
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 return longPressDragObserver.onDrag(dragDistance)
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 dragEnabled = false
                 dragStarted = false
                 longPressDragObserver.onStop(velocity)
@@ -177,7 +177,7 @@
             changes.all { it.changedToUpIgnoreConsumed() }
         ) {
             dragEnabled = false
-            longPressDragObserver.onStop(PxPosition.Origin)
+            longPressDragObserver.onStop(Offset.Zero)
         }
         return changes
     }
@@ -191,7 +191,7 @@
         }
     }
 
-    val onLongPress = { pxPosition: PxPosition ->
+    val onLongPress = { pxPosition: Offset ->
         dragEnabled = true
         longPressDragObserver.onLongPress(pxPosition)
     }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressGestureFilter.kt
index 5192ea1..2d9ad7a 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/LongPressGestureFilter.kt
@@ -34,7 +34,7 @@
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.temputils.delay
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 import kotlinx.coroutines.Job
 import kotlin.coroutines.CoroutineContext
@@ -50,7 +50,7 @@
  * (double tap, triple tap) and tap.
  */
 fun Modifier.longPressGestureFilter(
-    onLongPress: (PxPosition) -> Unit
+    onLongPress: (Offset) -> Unit
 ): Modifier = composed {
     @Suppress("DEPRECATION")
     val coroutineContext = CoroutineContextAmbient.current
@@ -62,7 +62,7 @@
 internal class LongPressGestureFilter(
     private val coroutineContext: CoroutineContext
 ) : PointerInputFilter() {
-    lateinit var onLongPress: (PxPosition) -> Unit
+    lateinit var onLongPress: (Offset) -> Unit
 
     var longPressTimeout = LongPressTimeout
 
@@ -71,7 +71,7 @@
     }
 
     private var state = State.Idle
-    private val pointerPositions = linkedMapOf<PointerId, PxPosition>()
+    private val pointerPositions = linkedMapOf<PointerId, Offset>()
     private var job: Job? = null
     private lateinit var customEventDispatcher: CustomEventDispatcher
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/PressIndicatorGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/PressIndicatorGestureFilter.kt
index 997f33b..dd17e9a0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/PressIndicatorGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/PressIndicatorGestureFilter.kt
@@ -26,9 +26,8 @@
 import androidx.ui.core.composed
 import androidx.ui.core.consumeDownChange
 import androidx.ui.core.pointerinput.PointerInputFilter
-import androidx.ui.geometry.Offset
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 
 /**
@@ -49,7 +48,7 @@
  */
 // TODO(b/139020678): Probably has shared functionality with other press based detectors.
 fun Modifier.pressIndicatorGestureFilter(
-    onStart: ((PxPosition) -> Unit)? = null,
+    onStart: ((Offset) -> Unit)? = null,
     onStop: (() -> Unit)? = null,
     onCancel: (() -> Unit)? = null,
     enabled: Boolean = true
@@ -70,7 +69,7 @@
      * This callback should be used to indicate that the press state should be shown.  An [Offset]
      * is provided to indicate where the first pointer made contact with this gesrure detector.
      */
-    var onStart: ((PxPosition) -> Unit)? = null
+    var onStart: ((Offset) -> Unit)? = null
 
     /**
      * Called if onStart was attempted to be called (it may have been null), no pointer movement
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawDragGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawDragGestureFilter.kt
index 4a38933..84e5170 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawDragGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawDragGestureFilter.kt
@@ -32,7 +32,7 @@
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.positionChange
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 import androidx.ui.util.fastForEach
 
@@ -50,7 +50,7 @@
      * @see onDrag
      * @see onStop
      */
-    fun onStart(downPosition: PxPosition) {}
+    fun onStart(downPosition: Offset) {}
 
     /**
      * Override to be notified when a distance has been dragged.
@@ -67,7 +67,7 @@
      * @param dragDistance The distance that has been dragged.  Reflects the average drag distance
      * of all pointers.
      */
-    fun onDrag(dragDistance: PxPosition) = PxPosition.Origin
+    fun onDrag(dragDistance: Offset) = Offset.Zero
 
     /**
      * Override to be notified when a drag has stopped.
@@ -76,7 +76,7 @@
      *
      * Only called if the last call between [onStart] and [onStop] was [onStart].
      */
-    fun onStop(velocity: PxPosition) {}
+    fun onStop(velocity: Offset) {}
 
     /**
      * Override to be notified when the drag has been cancelled.
@@ -134,7 +134,7 @@
 
 internal class RawDragGestureFilter : PointerInputFilter() {
     private val velocityTrackers: MutableMap<PointerId, VelocityTracker> = mutableMapOf()
-    private val downPositions: MutableMap<PointerId, PxPosition> = mutableMapOf()
+    private val downPositions: MutableMap<PointerId, Offset> = mutableMapOf()
     private var started = false
     var canStartDragging: (() -> Boolean)? = null
     lateinit var dragObserver: DragObserver
@@ -190,7 +190,7 @@
                         // velocityTracker at this point, that means at least one of the up events
                         // was not consumed so we should send velocity for flinging.
                         if (started) {
-                            val velocity: PxPosition? =
+                            val velocity: Offset? =
                                 if (velocityTracker != null) {
                                     changesToReturn = changesToReturn.map {
                                         it.consumeDownChange()
@@ -200,7 +200,7 @@
                                     null
                                 }
                             started = false
-                            dragObserver.onStop(velocity ?: PxPosition.Origin)
+                            dragObserver.onStop(velocity ?: Offset.Zero)
                         }
                     }
                 }
@@ -282,7 +282,7 @@
                         if (started) {
 
                             val consumed = dragObserver.onDrag(
-                                PxPosition(
+                                Offset(
                                     totalDx / changesToReturn.size,
                                     totalDy / changesToReturn.size
                                 )
@@ -311,12 +311,12 @@
     }
 }
 
-private fun Iterable<PxPosition>.averagePosition(): PxPosition {
+private fun Iterable<Offset>.averagePosition(): Offset {
     var x = 0f
     var y = 0f
     forEach {
         x += it.x
         y += it.y
     }
-    return PxPosition(x / count(), y / count())
+    return Offset(x / count(), y / count())
 }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawPressStartGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawPressStartGestureFilter.kt
index af4ef1c..03e3a5a 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawPressStartGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/RawPressStartGestureFilter.kt
@@ -26,7 +26,7 @@
 import androidx.ui.core.consumeDownChange
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Reacts if the first pointer input change it sees is an unconsumed down change, and if it reacts,
@@ -42,7 +42,7 @@
  * The theory is that this GestureDetector can be reused in PressIndicatorGestureDetector, and there
  * could be a corresponding RawPressReleasedGestureDetector.
  *
- * @param onPressStart Called when the first pointer "presses" on the GestureDetector.  [PxPosition]
+ * @param onPressStart Called when the first pointer "presses" on the GestureDetector.  [Offset]
  * is the position of that first pointer on press.
  * @param enabled If false, this GestureDetector will effectively act as if it is not in the
  * hierarchy.
@@ -50,7 +50,7 @@
  * react to and consume down changes.  Defaults to [PointerEventPass.PostUp].
  */
 fun Modifier.rawPressStartGestureFilter(
-    onPressStart: (PxPosition) -> Unit,
+    onPressStart: (Offset) -> Unit,
     enabled: Boolean = false,
     executionPass: PointerEventPass = PointerEventPass.PostUp
 ): Modifier = composed {
@@ -63,7 +63,7 @@
 
 internal class RawPressStartGestureFilter : PointerInputFilter() {
 
-    lateinit var onPressStart: (PxPosition) -> Unit
+    lateinit var onPressStart: (Offset) -> Unit
     private var enabled: Boolean = true
     private var executionPass = PointerEventPass.InitialDown
 
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/TapGestureFilter.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/TapGestureFilter.kt
index 1fe9557..e16f156 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/TapGestureFilter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/TapGestureFilter.kt
@@ -32,7 +32,7 @@
 import androidx.ui.core.gesture.customevents.DelayUpMessage
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 
 /**
@@ -60,7 +60,7 @@
 // TODO(b/139020678): Probably has shared functionality with other press based detectors.
 
 fun Modifier.tapGestureFilter(
-    onTap: (PxPosition) -> Unit
+    onTap: (Offset) -> Unit
 ): Modifier = composed {
     val filter = remember { TapGestureFilter() }
     filter.onTap = onTap
@@ -73,7 +73,7 @@
      *
      * This should be used to fire a state changing event as if a button was pressed.
      */
-    lateinit var onTap: (PxPosition) -> Unit
+    lateinit var onTap: (Offset) -> Unit
 
     /**
      * True when we are primed to call [onTap] and may be consuming all down changes.
@@ -82,7 +82,7 @@
 
     private var downPointers: MutableSet<PointerId> = mutableSetOf()
     private var upBlockedPointers: MutableSet<PointerId> = mutableSetOf()
-    private var lastPxPosition: PxPosition? = null
+    private var lastPxPosition: Offset? = null
 
     override fun onPointerInput(
         changes: List<PointerInputChange>,
@@ -95,7 +95,7 @@
             if (primed &&
                 changes.all { it.changedToUp() }
             ) {
-                val pointerPxPosition: PxPosition = changes[0].previous.position!!
+                val pointerPxPosition: Offset = changes[0].previous.position!!
                 if (changes.fastAny { !upBlockedPointers.contains(it.id) }) {
                     // If we are primed, all pointers went up, and at least one of the pointers is
                     // not blocked, we can fire, reset, and consume all of the up events.
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/gesture/util/VelocityTracker.kt b/ui/ui-core/src/main/java/androidx/ui/core/gesture/util/VelocityTracker.kt
index c2c45bc..b8b2e5c 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/gesture/util/VelocityTracker.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/gesture/util/VelocityTracker.kt
@@ -17,7 +17,7 @@
 package androidx.ui.core.gesture.util
 
 import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 import androidx.ui.unit.Velocity
 import androidx.ui.unit.inMilliseconds
@@ -56,7 +56,7 @@
     // TODO(shepshapard): VelocityTracker needs to be updated to be passed vectors instead of
     //   positions. For velocity tracking, the only thing that is important is the change in
     //   position over time.
-    fun addPosition(uptime: Uptime, position: PxPosition) {
+    fun addPosition(uptime: Uptime, position: Offset) {
         index = (index + 1) % HistorySize
         samples[index] = PointAtTime(position, uptime)
     }
@@ -110,7 +110,7 @@
             }
 
             oldestSample = sample
-            val position: PxPosition = sample.point
+            val position: Offset = sample.point
             x.add(position.x)
             y.add(position.y)
             time.add(-age)
@@ -130,7 +130,7 @@
                 val xSlope = xFit.coefficients[1]
                 val ySlope = yFit.coefficients[1]
                 return VelocityEstimate(
-                    pixelsPerSecond = PxPosition(
+                    pixelsPerSecond = Offset(
                         // Convert from pixels/ms to pixels/s
                         (xSlope * 1000),
                         (ySlope * 1000)
@@ -148,7 +148,7 @@
         // We're unable to make a velocity estimate but we did have at least one
         // valid pointer position.
         return VelocityEstimate(
-            pixelsPerSecond = PxPosition.Origin,
+            pixelsPerSecond = Offset.Zero,
             confidence = 1.0f,
             duration = newestSample.time - oldestSample.time,
             offset = newestSample.point - oldestSample.point
@@ -156,7 +156,7 @@
     }
 }
 
-private data class PointAtTime(val point: PxPosition, val time: Uptime)
+private data class PointAtTime(val point: Offset, val time: Uptime)
 
 /**
  * A two dimensional velocity estimate.
@@ -175,7 +175,7 @@
  */
 private data class VelocityEstimate(
     /** The number of pixels per second of velocity in the x and y directions. */
-    val pixelsPerSecond: PxPosition,
+    val pixelsPerSecond: Offset,
     /**
      * A value between 0.0 and 1.0 that indicates how well [VelocityTracker]
      * was able to fit a straight line to its position data.
@@ -192,9 +192,9 @@
      * The difference between the first and last position sample used
      * to compute [pixelsPerSecond].
      */
-    val offset: PxPosition
+    val offset: Offset
 ) {
     companion object {
-        val None = VelocityEstimate(PxPosition.Origin, 1f, Duration(0), PxPosition.Origin)
+        val None = VelocityEstimate(Offset.Zero, 1f, Duration(0), Offset.Zero)
     }
 }
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
index 2999035..7ee67e5 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
@@ -24,6 +24,7 @@
 import androidx.ui.core.PointerInputChange
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
+import androidx.ui.unit.plus
 
 /**
  * Organizes pointers and the [PointerInputFilter]s that they hit into a hierarchy such that
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/MotionEventAdapter.kt b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/MotionEventAdapter.kt
index 310ecf9..84aa612 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/MotionEventAdapter.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/MotionEventAdapter.kt
@@ -26,7 +26,7 @@
 import androidx.ui.core.PointerId
 import androidx.ui.core.PointerInputData
 import androidx.ui.unit.NanosecondsPerMillisecond
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 
 /**
@@ -144,7 +144,7 @@
     ): PointerInputData {
         val pointerCoords = MotionEvent.PointerCoords()
         motionEvent.getPointerCoords(index, pointerCoords)
-        val offset = PxPosition(pointerCoords.x, pointerCoords.y)
+        val offset = Offset(pointerCoords.x, pointerCoords.y)
 
         return PointerInputData(
             timestamp,
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/PointerInput.kt b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/PointerInput.kt
index dc3969c..2f339da 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/PointerInput.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/PointerInput.kt
@@ -24,7 +24,7 @@
 import androidx.ui.core.PointerInputChange
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.round
 
 /**
@@ -96,7 +96,7 @@
     internal val size: IntPxSize
         get() = layoutCoordinates.size
     internal val position: IntPxPosition
-        get() = layoutCoordinates.localToGlobal(PxPosition.Origin).round()
+        get() = layoutCoordinates.localToGlobal(Offset.Zero).round()
     internal val isAttached: Boolean
         get() = layoutCoordinates.isAttached
 }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/selection/Selectable.kt b/ui/ui-core/src/main/java/androidx/ui/core/selection/Selectable.kt
index 9a6b35d..f585a98 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/selection/Selectable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/selection/Selectable.kt
@@ -19,7 +19,7 @@
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.geometry.Rect
 import androidx.ui.text.AnnotatedString
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Provides [Selection] information for a composable to SelectionContainer. Composables who can
@@ -42,8 +42,8 @@
      *  if selection is applied to this composable.
      */
     fun getSelection(
-        startPosition: PxPosition,
-        endPosition: PxPosition,
+        startPosition: Offset,
+        endPosition: Offset,
         containerLayoutCoordinates: LayoutCoordinates,
         longPress: Boolean,
         previousSelection: Selection? = null,
@@ -51,14 +51,14 @@
     ): Selection?
 
     /**
-     * Return the [PxPosition] of a [SelectionHandle].
+     * Return the [Offset] of a [SelectionHandle].
      *
      * @param selection [Selection] contains the [SelectionHandle]
      * @param isStartHandle true if it's the start handle, false if it's the end handle.
      *
-     * @return [PxPosition] of this handle, based on which the [SelectionHandle] will be drawn.
+     * @return [Offset] of this handle, based on which the [SelectionHandle] will be drawn.
      */
-    fun getHandlePosition(selection: Selection, isStartHandle: Boolean): PxPosition
+    fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset
 
     /**
      * Return the [LayoutCoordinates] of the [Selectable].
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
index 9621cd8..3caf6b49 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
@@ -44,8 +44,7 @@
 import androidx.ui.unit.ipx
 import androidx.ui.unit.isFinite
 import androidx.ui.unit.max
-import androidx.ui.unit.px
-import androidx.ui.unit.round
+import kotlin.math.roundToInt
 
 /**
  * Default SelectionContainer to be used in order to make composables selectable by default.
@@ -134,7 +133,7 @@
                 } else {
                     if (isStartHandle) Alignment.TopStart else Alignment.TopEnd
                 },
-                offset = IntPxPosition(offset.x.px.round(), offset.y.px.round())
+                offset = IntPxPosition(offset.x.roundToInt().ipx, offset.y.roundToInt().ipx)
             ) {
                 val drag = Modifier.dragGestureFilter(
                     dragObserver = manager.handleDragObserver(isStartHandle = isStartHandle)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionManager.kt b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionManager.kt
index 6693f76..e0fb3dd 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionManager.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionManager.kt
@@ -33,8 +33,7 @@
 import androidx.ui.text.AnnotatedString
 import androidx.ui.text.length
 import androidx.ui.text.subSequence
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.px
+import androidx.ui.geometry.Offset
 import kotlin.math.max
 import kotlin.math.min
 
@@ -88,13 +87,13 @@
      * The beginning position of the drag gesture. Every time a new drag gesture starts, it wil be
      * recalculated.
      */
-    private var dragBeginPosition = PxPosition.Origin
+    private var dragBeginPosition = Offset.Zero
 
     /**
      * The total distance being dragged of the drag gesture. Every time a new drag gesture starts,
      * it will be zeroed out.
      */
-    private var dragTotalDistance = PxPosition.Origin
+    private var dragTotalDistance = Offset.Zero
 
     /**
      * A flag to check if the selection start or end handle is being dragged.
@@ -110,7 +109,7 @@
      * It is a [State] so reading it during the composition will cause recomposition every time
      * the position has been changed.
      */
-    var startHandlePosition by mutableStateOf<PxPosition?>(null, areEquivalent = StructurallyEqual)
+    var startHandlePosition by mutableStateOf<Offset?>(null, areEquivalent = StructurallyEqual)
         private set
 
     /**
@@ -119,7 +118,7 @@
      * It is a [State] so reading it during the composition will cause recomposition every time
      * the position has been changed.
      */
-    var endHandlePosition by mutableStateOf<PxPosition?>(null, areEquivalent = StructurallyEqual)
+    var endHandlePosition by mutableStateOf<Offset?>(null, areEquivalent = StructurallyEqual)
         private set
 
     init {
@@ -172,8 +171,8 @@
      * Iterates over the handlers, gets the selection for each Composable, and merges all the
      * returned [Selection]s.
      *
-     * @param startPosition [PxPosition] for the start of the selection
-     * @param endPosition [PxPosition] for the end of the selection
+     * @param startPosition [Offset] for the start of the selection
+     * @param endPosition [Offset] for the end of the selection
      * @param longPress the selection is a result of long press
      * @param previousSelection previous selection
      *
@@ -182,8 +181,8 @@
      */
     // This function is internal for testing purposes.
     internal fun mergeSelections(
-        startPosition: PxPosition,
-        endPosition: PxPosition,
+        startPosition: Offset,
+        endPosition: Offset,
         longPress: Boolean = false,
         previousSelection: Selection? = null,
         isStartHandle: Boolean = true
@@ -308,7 +307,7 @@
 
             var startTop = localLayoutCoordinates.childToLocal(
                 startLayoutCoordinates,
-                PxPosition(
+                Offset(
                     0f,
                     selection.start.selectable.getBoundingBox(selection.start.offset).top
                 )
@@ -316,7 +315,7 @@
 
             var endTop = localLayoutCoordinates.childToLocal(
                 endLayoutCoordinates,
-                PxPosition(
+                Offset(
                     0.0f,
                     selection.end.selectable.getBoundingBox(selection.end.offset).top
                 )
@@ -326,7 +325,7 @@
             endTop = localLayoutCoordinates.localToRoot(endTop)
 
             val top = min(startTop.y, endTop.y)
-            val bottom = max(startOffset.y, endOffset.y) + (HANDLE_HEIGHT.value * 4.0).px.value
+            val bottom = max(startOffset.y, endOffset.y) + (HANDLE_HEIGHT.value * 4.0).toFloat()
 
             return Rect(
                 left,
@@ -343,15 +342,15 @@
         // Call mergeSelections with an out of boundary input to inform all text widgets to
         // cancel their individual selection.
         mergeSelections(
-            startPosition = PxPosition(-1f, -1f),
-            endPosition = PxPosition(-1f, -1f),
+            startPosition = Offset(-1f, -1f),
+            endPosition = Offset(-1f, -1f),
             previousSelection = selection
         )
         if (selection != null) onSelectionChange(null)
     }
 
     val longPressDragObserver = object : LongPressDragObserver {
-        override fun onLongPress(pxPosition: PxPosition) {
+        override fun onLongPress(pxPosition: Offset) {
             if (draggingHandle) return
             val coordinates = containerLayoutCoordinates
             if (coordinates == null || !coordinates.isAttached) return
@@ -370,12 +369,12 @@
             // selection never started
             if (selection == null) return
             // Zero out the total distance that being dragged.
-            dragTotalDistance = PxPosition.Origin
+            dragTotalDistance = Offset.Zero
         }
 
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             // selection never started, did not consume any drag
-            if (selection == null) return PxPosition.Origin
+            if (selection == null) return Offset.Zero
 
             dragTotalDistance += dragDistance
             val newSelection = mergeSelections(
@@ -397,13 +396,13 @@
      * line's top offset, which is not included in current line's hit area. To be able to
      * hit current line, move up this y coordinates by 1 pixel.
      */
-    private fun getAdjustedCoordinates(position: PxPosition): PxPosition {
-        return PxPosition(position.x, position.y - 1f)
+    private fun getAdjustedCoordinates(position: Offset): Offset {
+        return Offset(position.x, position.y - 1f)
     }
 
     fun handleDragObserver(isStartHandle: Boolean): DragObserver {
         return object : DragObserver {
-            override fun onStart(downPosition: PxPosition) {
+            override fun onStart(downPosition: Offset) {
                 val selection = selection!!
                 // The LayoutCoordinates of the composable where the drag gesture should begin. This
                 // is used to convert the position of the beginning of the drag gesture from the
@@ -434,11 +433,11 @@
                 )
 
                 // Zero out the total distance that being dragged.
-                dragTotalDistance = PxPosition.Origin
+                dragTotalDistance = Offset.Zero
                 draggingHandle = true
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 val selection = selection!!
                 dragTotalDistance += dragDistance
 
@@ -480,7 +479,7 @@
                 return dragDistance
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 super.onStop(velocity)
                 draggingHandle = false
             }
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionRegistrarImpl.kt b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionRegistrarImpl.kt
index 724fc39..fb56822 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionRegistrarImpl.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/selection/SelectionRegistrarImpl.kt
@@ -17,7 +17,7 @@
 package androidx.ui.core.selection
 
 import androidx.ui.core.LayoutCoordinates
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 internal class SelectionRegistrarImpl : SelectionRegistrar {
     /**
@@ -67,15 +67,15 @@
                 val positionA =
                     if (layoutCoordinatesA != null) containerLayoutCoordinates.childToLocal(
                         layoutCoordinatesA,
-                        PxPosition.Origin
+                        Offset.Zero
                     )
-                    else PxPosition.Origin
+                    else Offset.Zero
                 val positionB =
                     if (layoutCoordinatesB != null) containerLayoutCoordinates.childToLocal(
                         layoutCoordinatesB,
-                        PxPosition.Origin
+                        Offset.Zero
                     )
-                    else PxPosition.Origin
+                    else Offset.Zero
 
                 if (positionA.y == positionB.y) compareValues(positionA.x, positionB.x)
                 else compareValues(positionA.y, positionB.y)
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
index e7ac627..ef6daec 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
@@ -26,7 +26,7 @@
 import androidx.ui.semantics.SemanticsPropertyKey
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastForEach
 
 /**
@@ -104,7 +104,7 @@
             return layoutNode.coordinates.globalBounds
         }
 
-    val globalPosition: PxPosition
+    val globalPosition: Offset
         get() {
             return layoutNode.coordinates.globalPosition
         }
@@ -275,7 +275,7 @@
  */
 internal val LayoutNode.outerSemantics: SemanticsWrapper?
     get() {
-        return (this as? LayoutNode)?.layoutNodeWrapper?.nearestSemantics
+        return (this as? LayoutNode)?.outerLayoutNodeWrapper?.nearestSemantics
     }
 
 /**
diff --git a/ui/ui-core/src/main/java/androidx/ui/res/FontResources.kt b/ui/ui-core/src/main/java/androidx/ui/res/FontResources.kt
index 17afe64..029768f 100644
--- a/ui/ui-core/src/main/java/androidx/ui/res/FontResources.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/res/FontResources.kt
@@ -27,7 +27,7 @@
 import androidx.ui.text.font.LoadedFontFamily
 import androidx.ui.text.font.ResourceFont
 import androidx.ui.text.font.SystemFontFamily
-import androidx.ui.text.typefaceFromFontFamily
+import androidx.ui.text.platform.typefaceFromFontFamily
 import androidx.ui.util.fastForEach
 
 private val cacheLock = Object()
diff --git a/ui/ui-core/src/main/java/androidx/ui/testutils/PointerInputTestUtil.kt b/ui/ui-core/src/main/java/androidx/ui/testutils/PointerInputTestUtil.kt
index f6fa05c..70fca2d 100644
--- a/ui/ui-core/src/main/java/androidx/ui/testutils/PointerInputTestUtil.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/testutils/PointerInputTestUtil.kt
@@ -25,7 +25,7 @@
 import androidx.ui.core.PointerInputHandler
 import androidx.ui.unit.Duration
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 import androidx.ui.unit.ipx
 
@@ -39,15 +39,15 @@
 ): PointerInputChange =
     PointerInputChange(
         PointerId(id),
-        PointerInputData(Uptime.Boot + duration, PxPosition(x, y), true),
+        PointerInputData(Uptime.Boot + duration, Offset(x, y), true),
         PointerInputData(null, null, false),
-        ConsumedData(PxPosition.Origin, false)
+        ConsumedData(Offset.Zero, false)
     )
 
 fun PointerInputChange.moveTo(duration: Duration, x: Float = 0f, y: Float = 0f) =
     copy(
         previous = current,
-        current = PointerInputData(Uptime.Boot + duration, PxPosition(x, y), true),
+        current = PointerInputData(Uptime.Boot + duration, Offset(x, y), true),
         consumed = ConsumedData()
     )
 
@@ -56,7 +56,7 @@
         previous = current,
         current = PointerInputData(
             current.uptime!! + duration,
-            PxPosition(current.position!!.x + dx, current.position.y + dy),
+            Offset(current.position!!.x + dx, current.position.y + dy),
             true
         ),
         consumed = ConsumedData()
@@ -72,7 +72,7 @@
 fun PointerInputChange.consume(dx: Float = 0f, dy: Float = 0f, downChange: Boolean = false) =
     copy(
         consumed = consumed.copy(
-            positionChange = PxPosition(
+            positionChange = Offset(
                 consumed.positionChange.x + dx,
                 consumed.positionChange.y + dy
             ), downChange = consumed.downChange || downChange
diff --git a/ui/ui-core/src/main/res/values/ids.xml b/ui/ui-core/src/main/res/values/ids.xml
index fbc3744..0d949ca 100644
--- a/ui/ui-core/src/main/res/values/ids.xml
+++ b/ui/ui-core/src/main/res/values/ids.xml
@@ -50,4 +50,5 @@
     <item name="accessibility_custom_action_30" type="id"/>
     <item name="accessibility_custom_action_31" type="id"/>
     <item name="wrapped_composition_tag" type="id" />
+    <item name="inspection_slot_table_set" type="id" />
 </resources>
\ No newline at end of file
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/LayoutNodeTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/LayoutNodeTest.kt
index 977a5c9..b10b89c 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/LayoutNodeTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/LayoutNodeTest.kt
@@ -18,12 +18,13 @@
 import androidx.test.filters.SmallTest
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
-import androidx.ui.core.pointerinput.resize
 import androidx.ui.unit.IntPxPosition
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.anyOrNull
+import com.nhaarman.mockitokotlin2.doAnswer
 import com.nhaarman.mockitokotlin2.doReturn
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.spy
@@ -37,7 +38,6 @@
 import org.junit.rules.ExpectedException
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import org.mockito.Mockito.mock
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
@@ -343,11 +343,11 @@
         node0.place(x0, y0)
         node1.place(x1, y1)
 
-        val globalPosition = PxPosition(250f, 300f)
+        val globalPosition = Offset(250f, 300f)
 
         val expectedX = globalPosition.x - x0.value.toFloat() - x1.value.toFloat()
         val expectedY = globalPosition.y - y0.value.toFloat() - y1.value.toFloat()
-        val expectedPosition = PxPosition(expectedX, expectedY)
+        val expectedPosition = Offset(expectedX, expectedY)
 
         val result = node1.coordinates.globalToLocal(globalPosition)
 
@@ -368,11 +368,11 @@
         node0.place(x0, y0)
         node1.place(x1, y1)
 
-        val globalPosition = PxPosition(250f, 300f)
+        val globalPosition = Offset(250f, 300f)
 
         val expectedX = globalPosition.x - x0.value.toFloat() - x1.value.toFloat()
         val expectedY = globalPosition.y - y0.value.toFloat() - y1.value.toFloat()
-        val expectedPosition = PxPosition(expectedX, expectedY)
+        val expectedPosition = Offset(expectedX, expectedY)
 
         val result = node1.coordinates.globalToLocal(globalPosition)
 
@@ -393,11 +393,11 @@
         node0.place(x0, y0)
         node1.place(x1, y1)
 
-        val localPosition = PxPosition(5f, 15f)
+        val localPosition = Offset(5f, 15f)
 
         val expectedX = localPosition.x + x0.value.toFloat() + x1.value.toFloat()
         val expectedY = localPosition.y + y0.value.toFloat() + y1.value.toFloat()
-        val expectedPosition = PxPosition(expectedX, expectedY)
+        val expectedPosition = Offset(expectedX, expectedY)
 
         val result = node1.coordinates.localToGlobal(localPosition)
 
@@ -418,11 +418,11 @@
         node0.place(x0, y0)
         node1.place(x1, y1)
 
-        val localPosition = PxPosition(5.ipx, 15.ipx)
+        val localPosition = Offset(5f, 15f)
 
         val expectedX = localPosition.x + x0.value.toFloat() + x1.value.toFloat()
         val expectedY = localPosition.y + y0.value.toFloat() + y1.value.toFloat()
-        val expectedPosition = PxPosition(expectedX, expectedY)
+        val expectedPosition = Offset(expectedX, expectedY)
 
         val result = node1.coordinates.localToGlobal(localPosition)
 
@@ -435,9 +435,9 @@
         node.attach(mockOwner(IntPxPosition(20.ipx, 20.ipx)))
         node.place(100.ipx, 10.ipx)
 
-        val result = node.coordinates.localToGlobal(PxPosition.Origin)
+        val result = node.coordinates.localToGlobal(Offset.Zero)
 
-        assertEquals(PxPosition(120f, 30f), result)
+        assertEquals(Offset(120f, 30f), result)
     }
 
     @Test
@@ -446,9 +446,9 @@
         node.attach(mockOwner(IntPxPosition(20.ipx, 20.ipx)))
         node.place(100.ipx, 10.ipx)
 
-        val result = node.coordinates.localToGlobal(PxPosition.Origin)
+        val result = node.coordinates.localToGlobal(Offset.Zero)
 
-        assertEquals(PxPosition(120.ipx, 30.ipx), result)
+        assertEquals(Offset(120f, 30f), result)
     }
 
     @Test
@@ -463,11 +463,11 @@
         node0.place(100.ipx, 10.ipx)
         node1.place(x1, y1)
 
-        val localPosition = PxPosition(5f, 15f)
+        val localPosition = Offset(5f, 15f)
 
         val expectedX = localPosition.x + x1.value.toFloat()
         val expectedY = localPosition.y + y1.value.toFloat()
-        val expectedPosition = PxPosition(expectedX, expectedY)
+        val expectedPosition = Offset(expectedX, expectedY)
 
         val result = node0.coordinates.childToLocal(node1.coordinates, localPosition)
 
@@ -485,7 +485,7 @@
 
         thrown.expect(IllegalStateException::class.java)
 
-        node2.coordinates.childToLocal(node1.coordinates, PxPosition(5f, 15f))
+        node2.coordinates.childToLocal(node1.coordinates, Offset(5f, 15f))
     }
 
     @Test
@@ -498,14 +498,14 @@
 
         thrown.expect(IllegalStateException::class.java)
 
-        node1.coordinates.childToLocal(node0.coordinates, PxPosition(5f, 15f))
+        node1.coordinates.childToLocal(node0.coordinates, Offset(5f, 15f))
     }
 
     @Test
     fun testChildToLocalTheSameNode() {
         val node = LayoutNode()
         node.attach(mockOwner())
-        val position = PxPosition(5f, 15f)
+        val position = Offset(5f, 15f)
 
         val result = node.coordinates.childToLocal(node.coordinates, position)
 
@@ -523,7 +523,7 @@
 
         val actual = child.coordinates.positionInRoot
 
-        assertEquals(PxPosition(-50.ipx, 90.ipx), actual)
+        assertEquals(Offset(-50f, 90f), actual)
     }
 
     @Test
@@ -536,7 +536,7 @@
 
         val actual = child.coordinates.positionInRoot
 
-        assertEquals(PxPosition(50.ipx, 80.ipx), actual)
+        assertEquals(Offset(50f, 80f), actual)
     }
 
     @Test
@@ -548,9 +548,9 @@
         parent.place(-100.ipx, 10.ipx)
         child.place(50.ipx, 80.ipx)
 
-        val actual = parent.coordinates.childToLocal(child.coordinates, PxPosition.Origin)
+        val actual = parent.coordinates.childToLocal(child.coordinates, Offset.Zero)
 
-        assertEquals(PxPosition(50f, 80f), actual)
+        assertEquals(Offset(50f, 80f), actual)
     }
 
     @Test
@@ -565,9 +565,9 @@
         parent.place(23.ipx, -13.ipx)
         child.place(-3.ipx, 11.ipx)
 
-        val actual = grandParent.coordinates.childToLocal(child.coordinates, PxPosition.Origin)
+        val actual = grandParent.coordinates.childToLocal(child.coordinates, Offset.Zero)
 
-        assertEquals(PxPosition(20f, -2f), actual)
+        assertEquals(Offset(20f, -2f), actual)
     }
 
     // LayoutNode shouldn't allow adding beyond the count
@@ -664,14 +664,14 @@
         val drawModifier = Modifier.drawBehind { }
 
         layoutNode.modifier = drawModifier
-        val oldLayoutNodeWrapper = layoutNode.layoutNodeWrapper
+        val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertFalse(oldLayoutNodeWrapper.isAttached)
 
         layoutNode.attach(mockOwner())
         assertTrue(oldLayoutNodeWrapper.isAttached)
 
         layoutNode.modifier = Modifier.drawBehind { }
-        val newLayoutNodeWrapper = layoutNode.layoutNodeWrapper
+        val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertTrue(newLayoutNodeWrapper.isAttached)
         assertFalse(oldLayoutNodeWrapper.isAttached)
     }
@@ -691,7 +691,7 @@
         )
         assertEquals(
             layoutNode2.innerLayoutNodeWrapper,
-            layoutNode.layoutNodeWrapper.parentCoordinates
+            layoutNode.outerLayoutNodeWrapper.parentCoordinates
         )
     }
 
@@ -707,7 +707,7 @@
             }
         val hit = mutableListOf<PointerInputFilter>()
 
-        layoutNode.hitTest(PxPosition(0.ipx, 0.ipx), hit)
+        layoutNode.hitTest(Offset(0f, 0f), hit)
 
         assertThat(hit).isEqualTo(listOf(pointerInputFilter))
     }
@@ -724,17 +724,17 @@
             }
         val hit = mutableListOf<PointerInputFilter>()
 
-        layoutNode.hitTest(PxPosition(-1.ipx, -1.ipx), hit)
-        layoutNode.hitTest(PxPosition(0.ipx, -1.ipx), hit)
-        layoutNode.hitTest(PxPosition(1.ipx, -1.ipx), hit)
+        layoutNode.hitTest(Offset(-1f, -1f), hit)
+        layoutNode.hitTest(Offset(0f, -1f), hit)
+        layoutNode.hitTest(Offset(1f, -1f), hit)
 
-        layoutNode.hitTest(PxPosition(-1.ipx, 0.ipx), hit)
+        layoutNode.hitTest(Offset(-1f, 0f), hit)
         // 0, 0 would hit
-        layoutNode.hitTest(PxPosition(1.ipx, 0.ipx), hit)
+        layoutNode.hitTest(Offset(1f, 0f), hit)
 
-        layoutNode.hitTest(PxPosition(-1.ipx, 1.ipx), hit)
-        layoutNode.hitTest(PxPosition(0.ipx, 1.ipx), hit)
-        layoutNode.hitTest(PxPosition(1.ipx, 1.ipx), hit)
+        layoutNode.hitTest(Offset(-1f, 1f), hit)
+        layoutNode.hitTest(Offset(0f, 1f), hit)
+        layoutNode.hitTest(Offset(1f, 1f), hit)
 
         assertThat(hit).isEmpty()
     }
@@ -789,9 +789,9 @@
             }
 
         val offset = when (numberOfChildrenHit) {
-            3 -> PxPosition(250f, 250f)
-            2 -> PxPosition(150f, 150f)
-            1 -> PxPosition(50f, 50f)
+            3 -> Offset(250f, 250f)
+            2 -> Offset(150f, 150f)
+            1 -> Offset(50f, 50f)
             else -> throw IllegalStateException()
         }
 
@@ -877,8 +877,8 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(25f, 25f)
-        val offset2 = PxPosition(75f, 75f)
+        val offset1 = Offset(25f, 25f)
+        val offset2 = Offset(75f, 75f)
 
         val hit1 = mutableListOf<PointerInputFilter>()
         val hit2 = mutableListOf<PointerInputFilter>()
@@ -954,9 +954,9 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(25f, 25f)
-        val offset2 = PxPosition(75f, 75f)
-        val offset3 = PxPosition(125f, 125f)
+        val offset1 = Offset(25f, 25f)
+        val offset2 = Offset(75f, 75f)
+        val offset3 = Offset(125f, 125f)
 
         val hit1 = mutableListOf<PointerInputFilter>()
         val hit2 = mutableListOf<PointerInputFilter>()
@@ -1016,9 +1016,9 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(50f, 25f)
-        val offset2 = PxPosition(50f, 75f)
-        val offset3 = PxPosition(50f, 125f)
+        val offset1 = Offset(50f, 25f)
+        val offset2 = Offset(50f, 75f)
+        val offset3 = Offset(50f, 125f)
 
         val hit1 = mutableListOf<PointerInputFilter>()
         val hit2 = mutableListOf<PointerInputFilter>()
@@ -1078,9 +1078,9 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(25f, 50f)
-        val offset2 = PxPosition(75f, 50f)
-        val offset3 = PxPosition(125f, 50f)
+        val offset1 = Offset(25f, 50f)
+        val offset2 = Offset(75f, 50f)
+        val offset3 = Offset(125f, 50f)
 
         val hit1 = mutableListOf<PointerInputFilter>()
         val hit2 = mutableListOf<PointerInputFilter>()
@@ -1164,21 +1164,21 @@
             attach(mockOwner())
         }
 
-        val offsetThatHits1 = PxPosition(1f, 1f)
-        val offsetThatHits2 = PxPosition(3f, 1f)
-        val offsetThatHits3 = PxPosition(1f, 3f)
-        val offsetThatHits4 = PxPosition(3f, 3f)
+        val offsetThatHits1 = Offset(1f, 1f)
+        val offsetThatHits2 = Offset(3f, 1f)
+        val offsetThatHits3 = Offset(1f, 3f)
+        val offsetThatHits4 = Offset(3f, 3f)
 
         val offsetsThatMiss =
             listOf(
-                PxPosition(1f, 0f),
-                PxPosition(3f, 0f),
-                PxPosition(0f, 1f),
-                PxPosition(4f, 1f),
-                PxPosition(0f, 3f),
-                PxPosition(4f, 3f),
-                PxPosition(1f, 4f),
-                PxPosition(3f, 4f)
+                Offset(1f, 0f),
+                Offset(3f, 0f),
+                Offset(0f, 1f),
+                Offset(4f, 1f),
+                Offset(0f, 3f),
+                Offset(4f, 3f),
+                Offset(1f, 4f),
+                Offset(3f, 4f)
             )
 
         val hit1 = mutableListOf<PointerInputFilter>()
@@ -1244,14 +1244,14 @@
             attach(mockOwner(IntPxPosition(1.ipx, 1.ipx)))
         }
 
-        val offsetThatHits1 = PxPosition(2f, 2f)
-        val offsetThatHits2 = PxPosition(2f, 1f)
-        val offsetThatHits3 = PxPosition(1f, 2f)
+        val offsetThatHits1 = Offset(2f, 2f)
+        val offsetThatHits2 = Offset(2f, 1f)
+        val offsetThatHits3 = Offset(1f, 2f)
         val offsetsThatMiss =
             listOf(
-                PxPosition(0f, 0f),
-                PxPosition(0f, 1f),
-                PxPosition(1f, 0f)
+                Offset(0f, 0f),
+                Offset(0f, 1f),
+                Offset(1f, 0f)
             )
 
         val hit1 = mutableListOf<PointerInputFilter>()
@@ -1303,7 +1303,7 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(50f, 75f)
+        val offset1 = Offset(50f, 75f)
 
         val hit = mutableListOf<PointerInputFilter>()
 
@@ -1347,7 +1347,7 @@
         }.apply {
             attach(mockOwner())
         }
-        val offset1 = PxPosition(499f, 499f)
+        val offset1 = Offset(499f, 499f)
 
         val hit = mutableListOf<PointerInputFilter>()
 
@@ -1402,7 +1402,7 @@
             attach(mockOwner())
         }
 
-        val offset1 = PxPosition(499f, 499f)
+        val offset1 = Offset(499f, 499f)
 
         val hit = mutableListOf<PointerInputFilter>()
 
@@ -1447,7 +1447,7 @@
             attach(mockOwner())
         }
 
-        val offset = PxPosition(50f, 50f)
+        val offset = Offset(50f, 50f)
 
         val hit = mutableListOf<PointerInputFilter>()
 
@@ -1474,7 +1474,7 @@
             attach(mockOwner())
         }
 
-        val offset = PxPosition.Origin
+        val offset = Offset.Zero
 
         val hit = mutableListOf<PointerInputFilter>()
 
@@ -1519,7 +1519,7 @@
 
         // Act.
 
-        parent.hitTest(PxPosition(1f, 1f), hit)
+        parent.hitTest(Offset(1f, 1f), hit)
 
         // Assert.
 
@@ -1573,30 +1573,47 @@
         return Triple(layoutNode, child1, child2)
     }
 
-    private fun mockOwner(
-        position: IntPxPosition = IntPxPosition.Origin,
-        targetRoot: LayoutNode = LayoutNode()
-    ): Owner =
-        mock {
-            on { calculatePosition() } doReturn position
-            on { root } doReturn targetRoot
-        }
-
-    private fun LayoutNode(x: Int, y: Int, x2: Int, y2: Int, modifier: Modifier = Modifier) =
-        LayoutNode().apply {
-            this.modifier = modifier
-            layoutDirection = LayoutDirection.Ltr
-            resize(x2.ipx - x.ipx, y2.ipx - y.ipx)
-            var wrapper: LayoutNodeWrapper? = layoutNodeWrapper
-            while (wrapper != null) {
-                wrapper.measureResult = innerLayoutNodeWrapper.measureResult
-                wrapper = (wrapper as? LayoutNodeWrapper)?.wrapped
-            }
-            place(x.ipx, y.ipx)
-        }
-
     private fun ZeroSizedLayoutNode() = LayoutNode(0, 0, 0, 0)
 
     private class PointerInputModifierImpl(override val pointerInputFilter: PointerInputFilter) :
         PointerInputModifier
 }
+
+internal fun mockOwner(
+    position: IntPxPosition = IntPxPosition.Origin,
+    targetRoot: LayoutNode = LayoutNode()
+): Owner =
+    @Suppress("UNCHECKED_CAST")
+    mock {
+        on { calculatePosition() } doReturn position
+        on { root } doReturn targetRoot
+        on { observeMeasureModelReads(any(), any()) } doAnswer {
+            (it.arguments[1] as () -> Unit).invoke()
+        }
+        on { observeLayoutModelReads(any(), any()) } doAnswer {
+            (it.arguments[1] as () -> Unit).invoke()
+        }
+    }
+
+internal fun LayoutNode(x: Int, y: Int, x2: Int, y2: Int, modifier: Modifier = Modifier) =
+    LayoutNode().apply {
+        this.modifier = modifier
+        measureBlocks = object : LayoutNode.NoIntrinsicsMeasureBlocks("not supported") {
+            override fun measure(
+                measureScope: MeasureScope,
+                measurables: List<Measurable>,
+                constraints: Constraints,
+                layoutDirection: LayoutDirection
+            ): MeasureScope.MeasureResult =
+                measureScope.layout(x2.ipx - x.ipx, y2.ipx - y.ipx) {}
+        }
+        attach(mockOwner())
+        remeasure(Constraints(), layoutDirection)
+        var wrapper: LayoutNodeWrapper? = outerLayoutNodeWrapper
+        while (wrapper != null) {
+            wrapper.measureResult = innerLayoutNodeWrapper.measureResult
+            wrapper = (wrapper as? LayoutNodeWrapper)?.wrapped
+        }
+        place(x.ipx, y.ipx)
+        detach()
+    }
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/PointerInputTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/PointerInputTest.kt
index e82abb5..aa8c1e8 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/PointerInputTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/PointerInputTest.kt
@@ -17,7 +17,7 @@
 package androidx.ui.core
 
 import androidx.test.filters.SmallTest
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 import androidx.ui.unit.milliseconds
 import org.hamcrest.CoreMatchers.`is`
@@ -185,7 +185,7 @@
             createPointerInputChange(11f, 13f, true, 11f, 13f, true, 0f, 0f, false)
         assertThat(
             pointerInputChange.positionChange(),
-            `is`(equalTo(PxPosition.Origin))
+            `is`(equalTo(Offset.Zero))
         )
     }
 
@@ -195,7 +195,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 0f, 0f, false)
         assertThat(
             pointerInputChange.positionChange(),
-            `is`(equalTo(PxPosition(6f, 12f)))
+            `is`(equalTo(Offset(6f, 12f)))
         )
     }
 
@@ -205,7 +205,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 5f, 9f, false)
         assertThat(
             pointerInputChange.positionChange(),
-            `is`(equalTo(PxPosition(1f, 3f)))
+            `is`(equalTo(Offset(1f, 3f)))
         )
     }
 
@@ -215,7 +215,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 6f, 12f, false)
         assertThat(
             pointerInputChange.positionChange(),
-            `is`(equalTo(PxPosition.Origin))
+            `is`(equalTo(Offset.Zero))
         )
     }
 
@@ -225,7 +225,7 @@
             createPointerInputChange(11f, 13f, true, 11f, 13f, true, 0f, 0f, false)
         assertThat(
             pointerInputChange.positionChangeIgnoreConsumed(),
-            `is`(equalTo(PxPosition.Origin))
+            `is`(equalTo(Offset.Zero))
         )
     }
 
@@ -235,7 +235,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 0f, 0f, false)
         assertThat(
             pointerInputChange.positionChangeIgnoreConsumed(),
-            `is`(equalTo(PxPosition(6f, 12f)))
+            `is`(equalTo(Offset(6f, 12f)))
         )
     }
 
@@ -245,7 +245,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 5f, 9f, false)
         assertThat(
             pointerInputChange.positionChangeIgnoreConsumed(),
-            `is`(equalTo(PxPosition(6f, 12f)))
+            `is`(equalTo(Offset(6f, 12f)))
         )
     }
 
@@ -255,7 +255,7 @@
             createPointerInputChange(8f, 16f, true, 2f, 4f, true, 6f, 12f, false)
         assertThat(
             pointerInputChange.positionChangeIgnoreConsumed(),
-            `is`(equalTo(PxPosition(6f, 12f)))
+            `is`(equalTo(Offset(6f, 12f)))
         )
     }
 
@@ -583,15 +583,15 @@
             PointerId(0),
             PointerInputData(
                 Uptime.Boot + 100.milliseconds,
-                PxPosition(currentX, currentY),
+                Offset(currentX, currentY),
                 currentDown
             ),
             PointerInputData(
                 Uptime.Boot + 0.milliseconds,
-                PxPosition(previousX, previousY),
+                Offset(previousX, previousY),
                 previousDown
             ),
-            ConsumedData(PxPosition(consumedX, consumedY), consumedDown)
+            ConsumedData(Offset(consumedX, consumedY), consumedDown)
         )
     }
 }
\ No newline at end of file
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/DoubleTapGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/DoubleTapGestureFilterTest.kt
index f7c77ed..7b7b741 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/DoubleTapGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/DoubleTapGestureFilterTest.kt
@@ -27,7 +27,7 @@
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -55,7 +55,7 @@
     private val DoubleTapTimeoutMillis = 100.milliseconds
     @Suppress("DEPRECATION")
     private val testContext = kotlinx.coroutines.test.TestCoroutineContext()
-    private val onDoubleTap: (PxPosition) -> Unit = mock()
+    private val onDoubleTap: (Offset) -> Unit = mock()
     private val customEventDispatcher: CustomEventDispatcher = mock()
     private lateinit var filter: DoubleTapGestureFilter
 
@@ -524,7 +524,7 @@
         filter::onPointerInput.invokeOverAllPasses(down2)
         filter::onPointerInput.invokeOverAllPasses(up2)
 
-        verify(onDoubleTap).invoke(PxPosition.Origin)
+        verify(onDoubleTap).invoke(Offset.Zero)
     }
 
     @Test
@@ -542,7 +542,7 @@
         filter::onPointerInput.invokeOverAllPasses(move2)
         filter::onPointerInput.invokeOverAllPasses(up2)
 
-        verify(onDoubleTap).invoke(PxPosition(3f, 5f))
+        verify(onDoubleTap).invoke(Offset(3f, 5f))
     }
 
     @Test
@@ -565,7 +565,7 @@
         filter::onPointerInput.invokeOverAllPasses(up2A, move2B2)
         filter::onPointerInput.invokeOverAllPasses(up2B)
 
-        verify(onDoubleTap).invoke(PxPosition(7f, 11f))
+        verify(onDoubleTap).invoke(Offset(7f, 11f))
     }
 
     // Tests that verify correct consumption behavior
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/LongPressGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/LongPressGestureFilterTest.kt
index d4b6d4a..3ff6562 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/LongPressGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/LongPressGestureFilterTest.kt
@@ -27,7 +27,7 @@
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -48,7 +48,7 @@
     private val LongPressTimeoutMillis = 100.milliseconds
     @Suppress("DEPRECATION")
     private val testContext = kotlinx.coroutines.test.TestCoroutineContext()
-    private val onLongPress: (PxPosition) -> Unit = mock()
+    private val onLongPress: (Offset) -> Unit = mock()
     private val customEventDispatcher: CustomEventDispatcher = mock()
     private lateinit var filter: LongPressGestureFilter
 
@@ -276,7 +276,7 @@
         filter::onPointerInput.invokeOverAllPasses(down)
         testContext.advanceTimeBy(100, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(13f, 17f))
+        verify(onLongPress).invoke(Offset(13f, 17f))
     }
 
     @Test
@@ -289,7 +289,7 @@
         filter::onPointerInput.invokeOverAllPasses(move)
         testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(7f, 5f))
+        verify(onLongPress).invoke(Offset(7f, 5f))
     }
 
     @Test
@@ -304,7 +304,7 @@
         filter::onPointerInput.invokeOverAllPasses(move0, down1)
         testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(13f, 17f))
+        verify(onLongPress).invoke(Offset(13f, 17f))
     }
 
     @Test
@@ -324,7 +324,7 @@
         filter::onPointerInput.invokeOverAllPasses(up0, move1)
         testContext.advanceTimeBy(25, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(11f, 19f))
+        verify(onLongPress).invoke(Offset(11f, 19f))
     }
 
     @Test
@@ -339,7 +339,7 @@
         filter::onPointerInput.invokeOverAllPasses(move0, down1)
         testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(27f, 29f))
+        verify(onLongPress).invoke(Offset(27f, 29f))
     }
 
     @Test
@@ -359,7 +359,7 @@
         filter::onPointerInput.invokeOverAllPasses(up0, move1)
         testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
 
-        verify(onLongPress).invoke(PxPosition(27f, 23f))
+        verify(onLongPress).invoke(Offset(27f, 23f))
     }
 
     // Tests that verify that consumption behavior
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/PressIndicatorGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/PressIndicatorGestureFilterTest.kt
index 42153bb..fa0f950 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/PressIndicatorGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/PressIndicatorGestureFilterTest.kt
@@ -26,7 +26,7 @@
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.nhaarman.mockitokotlin2.any
@@ -448,7 +448,7 @@
     fun onPointerInput_down_downPositionIsCorrect() {
         filter::onPointerInput
             .invokeOverAllPasses(down(0, 0.milliseconds, x = 13f, y = 17f))
-        verify(filter.onStart!!).invoke(PxPosition(13f, 17f))
+        verify(filter.onStart!!).invoke(Offset(13f, 17f))
     }
 
     // Verification of correct consumption behavior.
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawDragGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
index 7ef81c0..c8b3cf5 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
@@ -28,7 +28,7 @@
 import androidx.ui.testutils.up
 import androidx.ui.unit.Duration
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -219,8 +219,8 @@
         assertThat(onDragLog).hasSize(2)
         // OnDrags get's called twice each time because RawDragGestureDetector calls it on both
         // PostUp and PostDown and the distance is not consumed by PostUp.
-        assertThat(onDragLog[0].pxPosition).isEqualTo(PxPosition(5f, -2f))
-        assertThat(onDragLog[1].pxPosition).isEqualTo(PxPosition(5f, -2f))
+        assertThat(onDragLog[0].pxPosition).isEqualTo(Offset(5f, -2f))
+        assertThat(onDragLog[1].pxPosition).isEqualTo(Offset(5f, -2f))
     }
 
     @Test
@@ -251,14 +251,14 @@
         assertThat(onDragLog).hasSize(8)
         // OnDrags get's called twice each time because RawDragGestureDetector calls it on both
         // PostUp and PostDown and the distance is not consumed by PostUp.
-        assertThat(onDragLog[0].pxPosition).isEqualTo(PxPosition(3f, -5f))
-        assertThat(onDragLog[1].pxPosition).isEqualTo(PxPosition(3f, -5f))
-        assertThat(onDragLog[2].pxPosition).isEqualTo(PxPosition(-3f, 7f))
-        assertThat(onDragLog[3].pxPosition).isEqualTo(PxPosition(-3f, 7f))
-        assertThat(onDragLog[4].pxPosition).isEqualTo(PxPosition(6f, 10f))
-        assertThat(onDragLog[5].pxPosition).isEqualTo(PxPosition(6f, 10f))
-        assertThat(onDragLog[6].pxPosition).isEqualTo(PxPosition(-10f, -6f))
-        assertThat(onDragLog[7].pxPosition).isEqualTo(PxPosition(-10f, -6f))
+        assertThat(onDragLog[0].pxPosition).isEqualTo(Offset(3f, -5f))
+        assertThat(onDragLog[1].pxPosition).isEqualTo(Offset(3f, -5f))
+        assertThat(onDragLog[2].pxPosition).isEqualTo(Offset(-3f, 7f))
+        assertThat(onDragLog[3].pxPosition).isEqualTo(Offset(-3f, 7f))
+        assertThat(onDragLog[4].pxPosition).isEqualTo(Offset(6f, 10f))
+        assertThat(onDragLog[5].pxPosition).isEqualTo(Offset(6f, 10f))
+        assertThat(onDragLog[6].pxPosition).isEqualTo(Offset(-10f, -6f))
+        assertThat(onDragLog[7].pxPosition).isEqualTo(Offset(-10f, -6f))
     }
 
     @Test
@@ -287,10 +287,10 @@
         // 2 onDrags because RawDragGestureDetector calls onDrag on both PostUp and PostDown and the
         // distance is never consumed.
         assertThat(onDragLog[0].pxPosition).isEqualTo(
-            PxPosition(3f, -4f)
+            Offset(3f, -4f)
         )
         assertThat(onDragLog[1].pxPosition).isEqualTo(
-            PxPosition(3f, -4f)
+            Offset(3f, -4f)
         )
     }
 
@@ -439,7 +439,7 @@
             1f,
             0f
         )
-        dragObserver.dragConsume = PxPosition(7.ipx, (-11).ipx)
+        dragObserver.dragConsume = Offset(7f, -11f)
         var result = filter::onPointerInput.invokeOverPasses(
             change,
             PointerEventPass.InitialDown,
@@ -447,7 +447,7 @@
             PointerEventPass.PreDown,
             PointerEventPass.PostUp
         )
-        dragObserver.dragConsume = PxPosition.Origin
+        dragObserver.dragConsume = Offset.Zero
         result = filter::onPointerInput.invokeOverPasses(
             result,
             PointerEventPass.InitialDown,
@@ -461,7 +461,7 @@
 
     @Test
     fun onPointerInput_unblockedDownMoveCallBackDoesNotConsume_distanceChangeNotConsumed() {
-        dragObserver.dragConsume = PxPosition.Origin
+        dragObserver.dragConsume = Offset.Zero
 
         var change = down(0, 0.milliseconds)
         filter::onPointerInput.invokeOverAllPasses(change)
@@ -506,7 +506,7 @@
             3f,
             -5f
         )
-        dragObserver.dragConsume = PxPosition(7.ipx, (-11).ipx)
+        dragObserver.dragConsume = Offset(7f, -11f)
         var result = filter::onPointerInput.invokeOverPasses(
             change,
             PointerEventPass.InitialDown,
@@ -514,7 +514,7 @@
             PointerEventPass.PreDown,
             PointerEventPass.PostUp
         )
-        dragObserver.dragConsume = PxPosition.Origin
+        dragObserver.dragConsume = Offset.Zero
         result = filter::onPointerInput.invokeOverPasses(
             result,
             PointerEventPass.PostDown
@@ -552,7 +552,7 @@
         filter::onPointerInput.invokeOverAllPasses(move)
 
         assertThat(log.first { it.methodName == "onStart" }.pxPosition)
-            .isEqualTo(PxPosition(3f, 4f))
+            .isEqualTo(Offset(3f, 4f))
     }
 
     @Test
@@ -573,7 +573,7 @@
 
         assertThat(log.first { it.methodName == "onStart" }.pxPosition)
             // average position
-            .isEqualTo(PxPosition(3f, 4f))
+            .isEqualTo(Offset(3f, 4f))
     }
 
     // Tests that verify when onCancel should not be called.
@@ -630,7 +630,7 @@
         filter::onPointerInput.invokeOverAllPasses(move)
 
         assertThat(log.first { it.methodName == "onStart" }.pxPosition)
-            .isEqualTo(PxPosition(7f, 11f))
+            .isEqualTo(Offset(7f, 11f))
     }
 
     @Test
@@ -679,25 +679,25 @@
 
     data class LogItem(
         val methodName: String,
-        val pxPosition: PxPosition? = null
+        val pxPosition: Offset? = null
     )
 
     class MockDragObserver(
         private val log: MutableList<LogItem>,
-        var dragConsume: PxPosition? = null
+        var dragConsume: Offset? = null
     ) : DragObserver {
 
-        override fun onStart(downPosition: PxPosition) {
+        override fun onStart(downPosition: Offset) {
             log.add(LogItem("onStart", pxPosition = downPosition))
             super.onStart(downPosition)
         }
 
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             log.add(LogItem("onDrag", pxPosition = dragDistance))
             return dragConsume ?: super.onDrag(dragDistance)
         }
 
-        override fun onStop(velocity: PxPosition) {
+        override fun onStop(velocity: Offset) {
             log.add(LogItem("onStop", pxPosition = velocity))
             super.onStop(velocity)
         }
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawPressStartGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawPressStartGestureFilterTest.kt
index 40cec62..44127cf 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawPressStartGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawPressStartGestureFilterTest.kt
@@ -25,7 +25,7 @@
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.nhaarman.mockitokotlin2.any
@@ -143,7 +143,7 @@
     @Test
     fun onPointerInput_down_downPositionIsCorrect() {
         filter::onPointerInput.invokeOverAllPasses(down(0, x = 13f, y = 17f))
-        verify(filter.onPressStart).invoke(PxPosition(13f, 17f))
+        verify(filter.onPressStart).invoke(Offset(13f, 17f))
     }
 
     // Verification of correct consumption behavior.
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawScaleGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawScaleGestureFilterTest.kt
index 86cfa61..28c3495 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawScaleGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/RawScaleGestureFilterTest.kt
@@ -26,7 +26,7 @@
 import androidx.ui.testutils.moveBy
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -664,9 +664,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-1f, 0f))
+            .isEqualTo(Offset(-1f, 0f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(1f, 0f))
+            .isEqualTo(Offset(1f, 0f))
     }
 
     @Test
@@ -698,9 +698,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, -1f))
+            .isEqualTo(Offset(0f, -1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, 1f))
+            .isEqualTo(Offset(0f, 1f))
     }
 
     @Test
@@ -716,9 +716,9 @@
         val result = filter::onPointerInput.invokeOverAllPasses(change1, change2)
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-1f, -1f))
+            .isEqualTo(Offset(-1f, -1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(1f, 1f))
+            .isEqualTo(Offset(1f, 1f))
     }
 
     @Test
@@ -750,9 +750,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(1f, 0f))
+            .isEqualTo(Offset(1f, 0f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-1f, 0f))
+            .isEqualTo(Offset(-1f, 0f))
     }
 
     @Test
@@ -784,9 +784,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, 1f))
+            .isEqualTo(Offset(0f, 1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, -1f))
+            .isEqualTo(Offset(0f, -1f))
     }
 
     @Test
@@ -801,8 +801,8 @@
         change2 = change2.moveTo(10.milliseconds, 6f, 6f)
         val result = filter::onPointerInput.invokeOverAllPasses(change1, change2)
 
-        assertThat(result[0].consumed.positionChange).isEqualTo(PxPosition(2f, 2f))
-        assertThat(result[1].consumed.positionChange).isEqualTo(PxPosition(-2f, -2f))
+        assertThat(result[0].consumed.positionChange).isEqualTo(Offset(2f, 2f))
+        assertThat(result[1].consumed.positionChange).isEqualTo(Offset(-2f, -2f))
     }
 
     @Test
@@ -836,9 +836,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-1f, 0f))
+            .isEqualTo(Offset(-1f, 0f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(1f, 0f))
+            .isEqualTo(Offset(1f, 0f))
     }
 
     @Test
@@ -870,9 +870,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, -1f))
+            .isEqualTo(Offset(0f, -1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, 1f))
+            .isEqualTo(Offset(0f, 1f))
     }
 
     @Test
@@ -904,9 +904,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(1f, 0f))
+            .isEqualTo(Offset(1f, 0f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-1f, 0f))
+            .isEqualTo(Offset(-1f, 0f))
     }
 
     @Test
@@ -938,9 +938,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, 1f))
+            .isEqualTo(Offset(0f, 1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(0f, -1f))
+            .isEqualTo(Offset(0f, -1f))
     }
 
     @Test
@@ -972,9 +972,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(.5f, -1.5f))
+            .isEqualTo(Offset(.5f, -1.5f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-.5f, 1.5f))
+            .isEqualTo(Offset(-.5f, 1.5f))
     }
 
     @Test
@@ -1006,9 +1006,9 @@
         // Assert
 
         assertThat(result.first { it.id == PointerId(0) }.consumed.positionChange)
-            .isEqualTo(PxPosition(2f, -1f))
+            .isEqualTo(Offset(2f, -1f))
         assertThat(result.first { it.id == PointerId(1) }.consumed.positionChange)
-            .isEqualTo(PxPosition(-2f, 1f))
+            .isEqualTo(Offset(-2f, 1f))
     }
 
     @Test
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/TapGestureFilterTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/TapGestureFilterTest.kt
index 7024b0e..da46e86 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/TapGestureFilterTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/TapGestureFilterTest.kt
@@ -28,7 +28,7 @@
 import androidx.ui.testutils.moveTo
 import androidx.ui.testutils.up
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.milliseconds
 import com.nhaarman.mockitokotlin2.any
@@ -193,7 +193,7 @@
         filter::onPointerInput.invokeOverAllPasses(down)
         filter::onPointerInput.invokeOverAllPasses(up)
 
-        verify(filter.onTap).invoke(PxPosition(123f, 456f))
+        verify(filter.onTap).invoke(Offset(123f, 456f))
     }
 
     @Test
@@ -206,7 +206,7 @@
         filter::onPointerInput.invokeOverAllPasses(move)
         filter::onPointerInput.invokeOverAllPasses(up)
 
-        verify(filter.onTap).invoke(PxPosition(321f, 654f))
+        verify(filter.onTap).invoke(Offset(321f, 654f))
     }
 
     @Test
@@ -226,7 +226,7 @@
         filter::onPointerInput.invokeOverAllPasses(upA, moveB)
         filter::onPointerInput.invokeOverAllPasses(upB)
 
-        verify(filter.onTap).invoke(PxPosition(321f, 654f))
+        verify(filter.onTap).invoke(Offset(321f, 654f))
     }
 
     @Test
@@ -246,7 +246,7 @@
         filter::onPointerInput.invokeOverAllPasses(moveA2, upB)
         filter::onPointerInput.invokeOverAllPasses(upA)
 
-        verify(filter.onTap).invoke(PxPosition(123f, 456f))
+        verify(filter.onTap).invoke(Offset(123f, 456f))
     }
 
     @Test
@@ -262,7 +262,7 @@
         filter::onPointerInput.invokeOverAllPasses(up)
         filter::onCustomEvent.invokeOverAllPasses(delayUpNotConsumed)
 
-        verify(filter.onTap).invoke(PxPosition(123f, 456f))
+        verify(filter.onTap).invoke(Offset(123f, 456f))
     }
 
     @Test
@@ -285,7 +285,7 @@
         filter::onPointerInput.invokeOverAllPasses(upA, moveB)
         filter::onPointerInput.invokeOverAllPasses(upB)
 
-        verify(filter.onTap).invoke(PxPosition(321f, 654f))
+        verify(filter.onTap).invoke(Offset(321f, 654f))
     }
 
     @Test
@@ -312,7 +312,7 @@
         filter::onPointerInput.invokeOverAllPasses(upB)
         filter::onCustomEvent.invokeOverAllPasses(delayUpNotConsumed)
 
-        verify(filter.onTap).invoke(PxPosition(321f, 654f))
+        verify(filter.onTap).invoke(Offset(321f, 654f))
     }
 
     // Verification that the down changes should not be consumed.
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/gesture/util/VelocityTrackerTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/gesture/util/VelocityTrackerTest.kt
index 2a2f421..2e4b73f 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/gesture/util/VelocityTrackerTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/gesture/util/VelocityTrackerTest.kt
@@ -17,7 +17,7 @@
 package androidx.ui.core.gesture.util
 
 import androidx.ui.core.PointerInputData
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 import androidx.ui.unit.Velocity
 import androidx.ui.unit.milliseconds
@@ -119,7 +119,7 @@
  * This extracts the inline PxPosition to a separate function so that velocityEventData
  * creation doesn't make the function too long for dex.
  */
-private fun createPxPosition(width: Float, height: Float) = PxPosition(width, height)
+private fun createPxPosition(width: Float, height: Float) = Offset(width, height)
 
 val velocityEventData: List<PointerInputData> = listOf(
     PointerInputData(
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
index e2b89f1..3f2b7a1 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
@@ -33,7 +33,7 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
@@ -3008,19 +3008,19 @@
     override val parentCoordinates: LayoutCoordinates?
         get() = TODO("not implemented")
 
-    override fun globalToLocal(global: PxPosition): PxPosition {
+    override fun globalToLocal(global: Offset): Offset {
         TODO("not implemented")
     }
 
-    override fun localToGlobal(local: PxPosition): PxPosition {
+    override fun localToGlobal(local: Offset): Offset {
         return local
     }
 
-    override fun localToRoot(local: PxPosition): PxPosition {
+    override fun localToRoot(local: Offset): Offset {
         TODO("not implemented")
     }
 
-    override fun childToLocal(child: LayoutCoordinates, childLocal: PxPosition): PxPosition {
+    override fun childToLocal(child: LayoutCoordinates, childLocal: Offset): Offset {
         TODO("not implemented")
     }
 
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
index dfbc831..4a33465 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/PointerInputEventProcessorTest.kt
@@ -29,9 +29,10 @@
 import androidx.ui.core.consumePositionChange
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
 import androidx.ui.unit.ipx
+import androidx.ui.unit.minus
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
@@ -103,8 +104,8 @@
 
         root.insertAt(0, layoutNode)
 
-        val offset = PxPosition(100f, 200f)
-        val offset2 = PxPosition(300f, 400f)
+        val offset = Offset(100f, 200f)
+        val offset2 = Offset(300f, 400f)
 
         val events = arrayOf(
             PointerInputEvent(8712, Uptime.Boot + 3.milliseconds, offset, true),
@@ -164,7 +165,7 @@
 
         // Arrange
 
-        val childOffset = PxPosition(100f, 200f)
+        val childOffset = Offset(100f, 200f)
         val pointerInputFilter: PointerInputFilter = spy()
         val layoutNode = LayoutNode(
             100, 200, 301, 401,
@@ -176,10 +177,10 @@
         root.insertAt(0, layoutNode)
 
         val offsets = arrayOf(
-            PxPosition(100f, 200f),
-            PxPosition(300f, 200f),
-            PxPosition(100f, 400f),
-            PxPosition(300f, 400f)
+            Offset(100f, 200f),
+            Offset(300f, 200f),
+            Offset(100f, 400f),
+            Offset(300f, 400f)
         )
 
         val events = Array(4) { index ->
@@ -239,14 +240,14 @@
         root.insertAt(0, layoutNode)
 
         val offsets = arrayOf(
-            PxPosition(99f, 200f),
-            PxPosition(99f, 400f),
-            PxPosition(100f, 199f),
-            PxPosition(100f, 401f),
-            PxPosition(300f, 199f),
-            PxPosition(300f, 401f),
-            PxPosition(301f, 200f),
-            PxPosition(301f, 400f)
+            Offset(99f, 200f),
+            Offset(99f, 400f),
+            Offset(100f, 199f),
+            Offset(100f, 401f),
+            Offset(300f, 199f),
+            Offset(300f, 401f),
+            Offset(301f, 200f),
+            Offset(301f, 400f)
         )
 
         val events = Array(8) { index ->
@@ -314,9 +315,9 @@
         root.insertAt(0, parentLayoutNode)
 
         val offset = when (numberOfChildrenHit) {
-            3 -> PxPosition(250f, 250f)
-            2 -> PxPosition(150f, 150f)
-            1 -> PxPosition(50f, 50f)
+            3 -> Offset(250f, 250f)
+            2 -> Offset(150f, 150f)
+            1 -> Offset(50f, 50f)
             else -> throw IllegalStateException()
         }
 
@@ -393,21 +394,21 @@
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(100f, 0f),
+                Offset(100f, 0f),
                 true
             ),
-            previous = PointerInputData(Uptime.Boot + 3.milliseconds, PxPosition(0f, 0f), true),
-            consumed = ConsumedData(positionChange = PxPosition(0f, 0f))
+            previous = PointerInputData(Uptime.Boot + 3.milliseconds, Offset(0f, 0f), true),
+            consumed = ConsumedData(positionChange = Offset(0f, 0f))
         )
         val output = PointerInputChange(
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(100f, 0f),
+                Offset(100f, 0f),
                 true
             ),
-            previous = PointerInputData(Uptime.Boot + 3.milliseconds, PxPosition(0f, 0f), true),
-            consumed = ConsumedData(positionChange = PxPosition(13f, 0f))
+            previous = PointerInputData(Uptime.Boot + 3.milliseconds, Offset(0f, 0f), true),
+            consumed = ConsumedData(positionChange = Offset(13f, 0f))
         )
 
         val pointerInputFilter: PointerInputFilter =
@@ -435,13 +436,13 @@
         val down = PointerInputEvent(
             0,
             Uptime.Boot + 3.milliseconds,
-            PxPosition(0f, 0f),
+            Offset(0f, 0f),
             true
         )
         val move = PointerInputEvent(
             0,
             Uptime.Boot + 5.milliseconds,
-            PxPosition(100f, 0f),
+            Offset(100f, 0f),
             true
         )
 
@@ -518,14 +519,14 @@
         val middlePointerInputFilter: PointerInputFilter = spy()
         val parentPointerInputFilter: PointerInputFilter = spy()
 
-        val childOffset = PxPosition(cX1.toFloat(), cY1.toFloat())
+        val childOffset = Offset(cX1.toFloat(), cY1.toFloat())
         val childLayoutNode = LayoutNode(
             cX1, cY1, cX2, cY2,
             PointerInputModifierImpl(
                 childPointerInputFilter
             )
         )
-        val middleOffset = PxPosition(mX1.toFloat(), mY1.toFloat())
+        val middleOffset = Offset(mX1.toFloat(), mY1.toFloat())
         val middleLayoutNode: LayoutNode = LayoutNode(
             mX1, mY1, mX2, mY2,
             PointerInputModifierImpl(
@@ -549,7 +550,7 @@
 
         val additionalOffset = IntPxPosition(aOX.ipx, aOY.ipx)
 
-        val offset = PxPosition(pointerX.toFloat(), pointerY.toFloat())
+        val offset = Offset(pointerX.toFloat(), pointerY.toFloat())
 
         val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
 
@@ -669,8 +670,8 @@
             insertAt(0, childLayoutNode2)
         }
 
-        val offset1 = PxPosition(25f, 25f)
-        val offset2 = PxPosition(75f, 75f)
+        val offset1 = Offset(25f, 25f)
+        val offset2 = Offset(75f, 75f)
 
         val down = PointerInputEvent(
             Uptime.Boot + 5.milliseconds,
@@ -690,7 +691,7 @@
             id = PointerId(1),
             current = PointerInputData(
                 Uptime.Boot + 5.milliseconds,
-                offset2 - PxPosition(50f, 50f),
+                offset2 - Offset(50f, 50f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -780,9 +781,9 @@
             insertAt(2, childLayoutNode3)
         }
 
-        val offset1 = PxPosition(25f, 25f)
-        val offset2 = PxPosition(75f, 75f)
-        val offset3 = PxPosition(125f, 125f)
+        val offset1 = Offset(25f, 25f)
+        val offset2 = Offset(75f, 75f)
+        val offset3 = Offset(125f, 125f)
 
         val down = PointerInputEvent(
             Uptime.Boot + 5.milliseconds,
@@ -803,7 +804,7 @@
             id = PointerId(1),
             current = PointerInputData(
                 Uptime.Boot + 5.milliseconds,
-                offset2 - PxPosition(50f, 50f),
+                offset2 - Offset(50f, 50f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -813,7 +814,7 @@
             id = PointerId(2),
             current = PointerInputData(
                 Uptime.Boot + 5.milliseconds,
-                offset3 - PxPosition(100f, 100f),
+                offset3 - Offset(100f, 100f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -902,9 +903,9 @@
             insertAt(1, childLayoutNode2)
         }
 
-        val offset1 = PxPosition(50f, 25f)
-        val offset2 = PxPosition(50f, 75f)
-        val offset3 = PxPosition(50f, 125f)
+        val offset1 = Offset(50f, 25f)
+        val offset2 = Offset(50f, 75f)
+        val offset3 = Offset(50f, 125f)
 
         val down = PointerInputEvent(
             Uptime.Boot + 7.milliseconds,
@@ -925,7 +926,7 @@
             id = PointerId(1),
             current = PointerInputData(
                 Uptime.Boot + 7.milliseconds,
-                offset2 - PxPosition(25f, 50f),
+                offset2 - Offset(25f, 50f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -1007,9 +1008,9 @@
             insertAt(1, childLayoutNode2)
         }
 
-        val offset1 = PxPosition(25f, 50f)
-        val offset2 = PxPosition(75f, 50f)
-        val offset3 = PxPosition(125f, 50f)
+        val offset1 = Offset(25f, 50f)
+        val offset2 = Offset(75f, 50f)
+        val offset3 = Offset(125f, 50f)
 
         val down = PointerInputEvent(
             Uptime.Boot + 11.milliseconds,
@@ -1030,7 +1031,7 @@
             id = PointerId(1),
             current = PointerInputData(
                 Uptime.Boot + 11.milliseconds,
-                offset2 - PxPosition(50f, 25f),
+                offset2 - Offset(50f, 25f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -1140,21 +1141,21 @@
         }
         val offsetsThatHit =
             listOf(
-                PxPosition(1f, 1f),
-                PxPosition(3f, 1f),
-                PxPosition(1f, 3f),
-                PxPosition(3f, 3f)
+                Offset(1f, 1f),
+                Offset(3f, 1f),
+                Offset(1f, 3f),
+                Offset(3f, 3f)
             )
         val offsetsThatMiss =
             listOf(
-                PxPosition(1f, 0f),
-                PxPosition(3f, 0f),
-                PxPosition(0f, 1f),
-                PxPosition(4f, 1f),
-                PxPosition(0f, 3f),
-                PxPosition(4f, 3f),
-                PxPosition(1f, 4f),
-                PxPosition(3f, 4f)
+                Offset(1f, 0f),
+                Offset(3f, 0f),
+                Offset(0f, 1f),
+                Offset(4f, 1f),
+                Offset(0f, 3f),
+                Offset(4f, 3f),
+                Offset(1f, 4f),
+                Offset(3f, 4f)
             )
         val allOffsets = offsetsThatHit + offsetsThatMiss
         val pointerInputEvent =
@@ -1177,7 +1178,7 @@
                     id = PointerId(it.toLong()),
                     current = PointerInputData(
                         Uptime.Boot + 11.milliseconds,
-                        PxPosition(
+                        Offset(
                             if (offsetsThatHit[it].x == 1f) 1f else 0f,
                             if (offsetsThatHit[it].y == 1f) 1f else 0f
                         ),
@@ -1267,15 +1268,15 @@
         }
         val offsetsThatHit =
             listOf(
-                PxPosition(2f, 2f),
-                PxPosition(2f, 1f),
-                PxPosition(1f, 2f)
+                Offset(2f, 2f),
+                Offset(2f, 1f),
+                Offset(1f, 2f)
             )
         val offsetsThatMiss =
             listOf(
-                PxPosition(0f, 0f),
-                PxPosition(0f, 1f),
-                PxPosition(1f, 0f)
+                Offset(0f, 0f),
+                Offset(0f, 1f),
+                Offset(1f, 0f)
             )
         val allOffsets = offsetsThatHit + offsetsThatMiss
         val pointerInputEvent =
@@ -1299,7 +1300,7 @@
                     id = PointerId(it.toLong()),
                     current = PointerInputData(
                         Uptime.Boot + 11.milliseconds,
-                        offsetsThatHit[it] - PxPosition(1f, 1f),
+                        offsetsThatHit[it] - Offset(1f, 1f),
                         true
                     ),
                     previous = PointerInputData(null, null, false),
@@ -1341,7 +1342,7 @@
             insertAt(0, layoutNode)
         }
 
-        val offset1 = PxPosition(50f, 75f)
+        val offset1 = Offset(50f, 75f)
 
         val down = PointerInputEvent(
             Uptime.Boot + 7.milliseconds,
@@ -1354,7 +1355,7 @@
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 7.milliseconds,
-                offset1 - PxPosition(25f, 50f),
+                offset1 - Offset(25f, 50f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -1421,7 +1422,7 @@
             insertAt(0, layoutNode4)
         }
 
-        val offset1 = PxPosition(499f, 499f)
+        val offset1 = Offset(499f, 499f)
 
         val downEvent = PointerInputEvent(
             Uptime.Boot + 7.milliseconds,
@@ -1434,7 +1435,7 @@
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 7.milliseconds,
-                offset1 - PxPosition(1f + 2f + 3f + 4f, 5f + 6f + 7f + 8f),
+                offset1 - Offset(1f + 2f + 3f + 4f, 5f + 6f + 7f + 8f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -1500,7 +1501,7 @@
             insertAt(0, layoutNode5)
         }
 
-        val offset1 = PxPosition(499f, 499f)
+        val offset1 = Offset(499f, 499f)
 
         val downEvent = PointerInputEvent(
             Uptime.Boot + 3.milliseconds,
@@ -1513,7 +1514,7 @@
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 3.milliseconds,
-                offset1 - PxPosition(
+                offset1 - Offset(
                     1f + 2f + 3f + 4f + 5f,
                     6f + 7f + 8f + 9f + 10f
                 ),
@@ -1527,7 +1528,7 @@
             id = PointerId(0),
             current = PointerInputData(
                 Uptime.Boot + 3.milliseconds,
-                offset1 - PxPosition(3f + 4f + 5f, 8f + 9f + 10f),
+                offset1 - Offset(3f + 4f + 5f, 8f + 9f + 10f),
                 true
             ),
             previous = PointerInputData(null, null, false),
@@ -1605,7 +1606,7 @@
         }
 
         val down = PointerInputEvent(
-            1, Uptime.Boot + 0.milliseconds, PxPosition(50f, 50f), true
+            1, Uptime.Boot + 0.milliseconds, Offset(50f, 50f), true
         )
 
         // Act
@@ -1632,7 +1633,7 @@
         }
 
         val down = PointerInputEvent(
-            1, Uptime.Boot + 0.milliseconds, PxPosition(0f, 0f), true
+            1, Uptime.Boot + 0.milliseconds, Offset(0f, 0f), true
         )
 
         // Act
@@ -1667,7 +1668,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(250f, 250f),
+                Offset(250f, 250f),
                 true
             )
 
@@ -1676,7 +1677,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(250f, 250f),
+                    Offset(250f, 250f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -1727,7 +1728,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(200f, 200f),
+                Offset(200f, 200f),
                 true
             )
 
@@ -1738,13 +1739,13 @@
                     PointerInputEventData(
                         7,
                         Uptime.Boot + 10.milliseconds,
-                        PxPosition(200f, 200f),
+                        Offset(200f, 200f),
                         true
                     ),
                     PointerInputEventData(
                         9,
                         Uptime.Boot + 10.milliseconds,
-                        PxPosition(300f, 300f),
+                        Offset(300f, 300f),
                         true
                     )
                 )
@@ -1756,7 +1757,7 @@
                     id = PointerId(7),
                     current = PointerInputData(
                         Uptime.Boot + 5.milliseconds,
-                        PxPosition(200f, 200f),
+                        Offset(200f, 200f),
                         true
                     ),
                     previous = PointerInputData(null, null, false),
@@ -1770,12 +1771,12 @@
                     id = PointerId(7),
                     current = PointerInputData(
                         Uptime.Boot + 10.milliseconds,
-                        PxPosition(200f, 200f),
+                        Offset(200f, 200f),
                         true
                     ),
                     previous = PointerInputData(
                         Uptime.Boot + 5.milliseconds,
-                        PxPosition(200f, 200f),
+                        Offset(200f, 200f),
                         true
                     ),
                     consumed = ConsumedData()
@@ -1784,7 +1785,7 @@
                     id = PointerId(9),
                     current = PointerInputData(
                         Uptime.Boot + 10.milliseconds,
-                        PxPosition(300f, 300f),
+                        Offset(300f, 300f),
                         true
                     ),
                     previous = PointerInputData(null, null, false),
@@ -1848,7 +1849,7 @@
             PointerInputEventData(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(100f, 100f),
+                Offset(100f, 100f),
                 true
             )
 
@@ -1856,7 +1857,7 @@
             PointerInputEventData(
                 9,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(300f, 300f),
+                Offset(300f, 300f),
                 true
             )
 
@@ -1870,7 +1871,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(100f, 100f),
+                    Offset(100f, 100f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -1882,7 +1883,7 @@
                 id = PointerId(9),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(100f, 100f),
+                    Offset(100f, 100f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -1942,7 +1943,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(200f, 200f),
+                Offset(200f, 200f),
                 true
             )
 
@@ -1950,7 +1951,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 10.milliseconds,
-                PxPosition(300f, 300f),
+                Offset(300f, 300f),
                 true
             )
 
@@ -1959,7 +1960,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(200f, 200f),
+                    Offset(200f, 200f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -1971,12 +1972,12 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 10.milliseconds,
-                    PxPosition(300f, 300f),
+                    Offset(300f, 300f),
                     true
                 ),
                 previous = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(200f, 200f),
+                    Offset(200f, 200f),
                     true
                 ),
                 consumed = ConsumedData()
@@ -2031,7 +2032,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(200f, 200f),
+                Offset(200f, 200f),
                 true
             )
 
@@ -2040,7 +2041,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(200f, 200f),
+                    Offset(200f, 200f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -2090,7 +2091,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 5.milliseconds,
-                PxPosition(200f, 200f),
+                Offset(200f, 200f),
                 true
             )
 
@@ -2098,7 +2099,7 @@
             PointerInputEvent(
                 7,
                 Uptime.Boot + 10.milliseconds,
-                PxPosition(200f, 200f),
+                Offset(200f, 200f),
                 true
             )
 
@@ -2107,7 +2108,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 5.milliseconds,
-                    PxPosition(200f, 200f),
+                    Offset(200f, 200f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -2119,7 +2120,7 @@
                 id = PointerId(7),
                 current = PointerInputData(
                     Uptime.Boot + 10.milliseconds,
-                    PxPosition(200f, 200f),
+                    Offset(200f, 200f),
                     true
                 ),
                 previous = PointerInputData(null, null, false),
@@ -2179,7 +2180,7 @@
 
         root.insertAt(0, parentLayoutNode)
 
-        val offset = PxPosition(50f, 50f)
+        val offset = Offset(50f, 50f)
 
         val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
         val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
@@ -2245,7 +2246,7 @@
         root.insertAt(0, parentLayoutNode)
 
         val down =
-            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, PxPosition(50f, 50f), true)
+            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, Offset(50f, 50f), true)
 
         val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
 
@@ -2285,7 +2286,7 @@
 
         root.insertAt(0, parentLayoutNode)
 
-        val offset = PxPosition(50f, 50f)
+        val offset = Offset(50f, 50f)
 
         val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
         val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
@@ -2351,7 +2352,7 @@
         root.insertAt(0, parentLayoutNode)
 
         val down =
-            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, PxPosition(50f, 50f), true)
+            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, Offset(50f, 50f), true)
 
         val up = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, null, false)
 
@@ -2369,7 +2370,7 @@
     @Test
     fun process_downNoPointerInputModifiers_nothingInteractedWithAndNoMovementConsumed() {
         val pointerInputEvent =
-            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, PxPosition(0f, 0f), true)
+            PointerInputEvent(0, Uptime.Boot + 7.milliseconds, Offset(0f, 0f), true)
 
         val result: ProcessResult = pointerInputEventProcessor.process(pointerInputEvent)
 
@@ -2401,10 +2402,10 @@
 
         val offsets =
             listOf(
-                PxPosition(-1f, 0f),
-                PxPosition(0f, -1f),
-                PxPosition(1f, 0f),
-                PxPosition(0f, 1f)
+                Offset(-1f, 0f),
+                Offset(0f, -1f),
+                Offset(1f, 0f),
+                Offset(0f, 1f)
             )
         val pointerInputEvent =
             PointerInputEvent(
@@ -2442,7 +2443,7 @@
         )
         root.apply { insertAt(0, layoutNode) }
         val pointerInputEvent =
-            PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(0f, 0f), true)
+            PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(0f, 0f), true)
 
         // Act
 
@@ -2471,9 +2472,9 @@
             )
         )
         root.apply { insertAt(0, layoutNode) }
-        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(0f, 0f), true)
+        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(0f, 0f), true)
         pointerInputEventProcessor.process(down)
-        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(1f, 0f), true)
+        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(1f, 0f), true)
 
         // Act
 
@@ -2503,9 +2504,9 @@
             )
         )
         root.apply { insertAt(0, layoutNode) }
-        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(0f, 0f), true)
+        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(0f, 0f), true)
         pointerInputEventProcessor.process(down)
-        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(1f, 0f), true)
+        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(1f, 0f), true)
 
         // Act
 
@@ -2544,9 +2545,9 @@
             )
         )
         root.apply { insertAt(0, layoutNode) }
-        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(0f, 0f), true)
+        val down = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(0f, 0f), true)
         pointerInputEventProcessor.process(down)
-        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, PxPosition(1f, 0f), true)
+        val move = PointerInputEvent(0, Uptime.Boot + 11.milliseconds, Offset(1f, 0f), true)
 
         // Act
 
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/TestUtils.kt b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/TestUtils.kt
index 0e80752..31c540c 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/TestUtils.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/TestUtils.kt
@@ -16,22 +16,14 @@
 
 package androidx.ui.core.pointerinput
 
-import androidx.ui.core.AlignmentLine
-import androidx.ui.core.LayoutDirection
-import androidx.ui.core.LayoutNode
-import androidx.ui.core.LayoutNodeWrapper
-import androidx.ui.core.MeasureScope
-import androidx.ui.core.Modifier
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.PointerId
 import androidx.ui.core.PointerInputChange
 import androidx.ui.core.PointerInputData
 import androidx.ui.core.PointerInputHandler
-import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Uptime
-import androidx.ui.unit.ipx
 
 /**
  * This class enables Mockito to spy.
@@ -51,34 +43,10 @@
     }
 }
 
-internal fun LayoutNode(x: Int, y: Int, x2: Int, y2: Int, modifier: Modifier = Modifier) =
-    LayoutNode().apply {
-        this.modifier = modifier
-        layoutDirection = LayoutDirection.Ltr
-        resize(x2.ipx - x.ipx, y2.ipx - y.ipx)
-        var wrapper: LayoutNodeWrapper? = layoutNodeWrapper
-        while (wrapper != null) {
-            wrapper.measureResult = innerLayoutNodeWrapper.measureResult
-            wrapper = (wrapper as? LayoutNodeWrapper)?.wrapped
-        }
-        place(x.ipx, y.ipx)
-    }
-
-internal fun LayoutNode.resize(width: IntPx, height: IntPx) {
-    handleMeasureResult(
-        object : MeasureScope.MeasureResult {
-            override val width: IntPx = width
-            override val height: IntPx = height
-            override val alignmentLines: Map<AlignmentLine, IntPx> = emptyMap()
-            override fun placeChildren(layoutDirection: LayoutDirection) {}
-        }
-    )
-}
-
 internal fun PointerInputEventData(
     id: Int,
     uptime: Uptime,
-    position: PxPosition?,
+    position: Offset?,
     down: Boolean
 ): PointerInputEventData {
     val pointerInputData = PointerInputData(uptime, position, down)
@@ -88,7 +56,7 @@
 internal fun PointerInputEvent(
     id: Int,
     uptime: Uptime,
-    position: PxPosition?,
+    position: Offset?,
     down: Boolean
 ): PointerInputEvent {
     return PointerInputEvent(
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerDragTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerDragTest.kt
index 87f5948..57c608b 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerDragTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerDragTest.kt
@@ -21,7 +21,7 @@
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.text.style.TextDirection
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.doReturn
@@ -46,7 +46,7 @@
     private val containerLayoutCoordinates = mock<LayoutCoordinates> {
         on { isAttached } doReturn true
     }
-    private val childToLocal_result = PxPosition(300f, 400f)
+    private val childToLocal_result = Offset(300f, 400f)
 
     private val startSelectable = mock<Selectable>()
     private val endSelectable = mock<Selectable>()
@@ -107,8 +107,8 @@
         whenever(startSelectable.getLayoutCoordinates()).thenReturn(startLayoutCoordinates)
         whenever(endSelectable.getLayoutCoordinates()).thenReturn(endLayoutCoordinates)
 
-        whenever(startSelectable.getHandlePosition(any(), any())).thenReturn(PxPosition.Origin)
-        whenever(endSelectable.getHandlePosition(any(), any())).thenReturn(PxPosition.Origin)
+        whenever(startSelectable.getHandlePosition(any(), any())).thenReturn(Offset.Zero)
+        whenever(endSelectable.getHandlePosition(any(), any())).thenReturn(Offset.Zero)
 
         selectionManager.containerLayoutCoordinates = containerLayoutCoordinates
         selectionManager.onSelectionChange = spyLambda
@@ -123,12 +123,12 @@
 
     @Test
     fun handleDragObserver_onStart_startHandle_enable_draggingHandle_get_startHandle_info() {
-        selectionManager.handleDragObserver(isStartHandle = true).onStart(PxPosition.Origin)
+        selectionManager.handleDragObserver(isStartHandle = true).onStart(Offset.Zero)
 
         verify(containerLayoutCoordinates, times(1))
             .childToLocal(
                 child = startLayoutCoordinates,
-                childLocal = getAdjustedCoordinates(PxPosition.Origin)
+                childLocal = getAdjustedCoordinates(Offset.Zero)
             )
         verify_draggingHandle(expectedDraggingHandleValue = true)
         verify(spyLambda, times(0)).invoke(fakeResultSelection)
@@ -136,12 +136,12 @@
 
     @Test
     fun handleDragObserver_onStart_endHandle_enable_draggingHandle_get_endHandle_info() {
-        selectionManager.handleDragObserver(isStartHandle = false).onStart(PxPosition.Origin)
+        selectionManager.handleDragObserver(isStartHandle = false).onStart(Offset.Zero)
 
         verify(containerLayoutCoordinates, times(1))
             .childToLocal(
                 child = endLayoutCoordinates,
-                childLocal = getAdjustedCoordinates(PxPosition.Origin)
+                childLocal = getAdjustedCoordinates(Offset.Zero)
             )
         verify_draggingHandle(expectedDraggingHandleValue = true)
         verify(spyLambda, times(0)).invoke(fakeResultSelection)
@@ -150,15 +150,15 @@
     @Test
     fun handleDragObserver_onDrag_startHandle_reuse_endHandle_calls_getSelection_change_selection
                 () {
-        val dragDistance = PxPosition(100f, 100f)
-        selectionManager.handleDragObserver(isStartHandle = true).onStart(PxPosition.Origin)
+        val dragDistance = Offset(100f, 100f)
+        selectionManager.handleDragObserver(isStartHandle = true).onStart(Offset.Zero)
 
         val result = selectionManager.handleDragObserver(isStartHandle = true).onDrag(dragDistance)
 
         verify(containerLayoutCoordinates, times(1))
             .childToLocal(
                 child = endLayoutCoordinates,
-                childLocal = getAdjustedCoordinates(PxPosition.Origin)
+                childLocal = getAdjustedCoordinates(Offset.Zero)
             )
         verify(selectable, times(1))
             .getSelection(
@@ -177,15 +177,15 @@
     @Test
     fun handleDragObserver_onDrag_endHandle_resue_startHandle_calls_getSelection_change_selection
                 () {
-        val dragDistance = PxPosition(100f, 100f)
-        selectionManager.handleDragObserver(isStartHandle = false).onStart(PxPosition.Origin)
+        val dragDistance = Offset(100f, 100f)
+        selectionManager.handleDragObserver(isStartHandle = false).onStart(Offset.Zero)
 
         val result = selectionManager.handleDragObserver(isStartHandle = false).onDrag(dragDistance)
 
         verify(containerLayoutCoordinates, times(1))
             .childToLocal(
                 child = startLayoutCoordinates,
-                childLocal = getAdjustedCoordinates(PxPosition.Origin)
+                childLocal = getAdjustedCoordinates(Offset.Zero)
             )
         verify(selectable, times(1))
             .getSelection(
@@ -203,21 +203,21 @@
 
     @Test
     fun handleDragObserver_onStop_disable_draggingHandle() {
-        selectionManager.handleDragObserver(false).onStart(PxPosition.Origin)
-        selectionManager.handleDragObserver(false).onDrag(PxPosition.Origin)
+        selectionManager.handleDragObserver(false).onStart(Offset.Zero)
+        selectionManager.handleDragObserver(false).onDrag(Offset.Zero)
 
-        selectionManager.handleDragObserver(false).onStop(PxPosition.Origin)
+        selectionManager.handleDragObserver(false).onStop(Offset.Zero)
 
         verify_draggingHandle(expectedDraggingHandleValue = false)
     }
 
-    private fun getAdjustedCoordinates(position: PxPosition): PxPosition {
-        return PxPosition(position.x, position.y - 1f)
+    private fun getAdjustedCoordinates(position: Offset): Offset {
+        return Offset(position.x, position.y - 1f)
     }
 
     private fun verify_draggingHandle(expectedDraggingHandleValue: Boolean) {
         // Verify draggingHandle is true, by verifying LongPress does nothing. Vice Versa.
-        val position = PxPosition(100f, 100f)
+        val position = Offset(100f, 100f)
         selectionManager.longPressDragObserver.onLongPress(position)
         verify(selectable, times(if (expectedDraggingHandleValue) 0 else 1))
             .getSelection(
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
index 1c69bfc..6fc39b6 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
@@ -21,7 +21,7 @@
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.text.style.TextDirection
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.anyOrNull
@@ -109,7 +109,7 @@
 
     @Test
     fun longPressDragObserver_onLongPress_calls_getSelection_change_selection() {
-        val position = PxPosition(100f, 100f)
+        val position = Offset(100f, 100f)
 
         selectionManager.longPressDragObserver.onLongPress(position)
 
@@ -129,10 +129,10 @@
     @Test
     fun longPressDragObserver_onDragStart_reset_dragTotalDistance() {
         // Setup. Make sure selectionManager.dragTotalDistance is not 0.
-        val dragDistance1 = PxPosition(15f, 10f)
-        val beginPosition1 = PxPosition(30f, 20f)
-        val dragDistance2 = PxPosition(100f, 300f)
-        val beginPosition2 = PxPosition(300f, 200f)
+        val dragDistance1 = Offset(15f, 10f)
+        val beginPosition1 = Offset(30f, 20f)
+        val dragDistance2 = Offset(100f, 300f)
+        val beginPosition2 = Offset(300f, 200f)
         selectionManager.longPressDragObserver.onLongPress(beginPosition1)
         selectionManager.longPressDragObserver.onDragStart()
         selectionManager.longPressDragObserver.onDrag(dragDistance1)
@@ -162,8 +162,8 @@
 
     @Test
     fun longPressDragObserver_onDrag_calls_getSelection_change_selection() {
-        val dragDistance = PxPosition(15f, 10f)
-        val beginPosition = PxPosition(30f, 20f)
+        val dragDistance = Offset(15f, 10f)
+        val beginPosition = Offset(30f, 20f)
         selectionManager.longPressDragObserver.onLongPress(beginPosition)
         selectionManager.selection = fakeInitialSelection
         selection = fakeInitialSelection
@@ -186,13 +186,13 @@
 
     @Test
     fun longPressDragObserver_onDrag_directly_not_call_getSelection_not_change_selection() {
-        val dragDistance = PxPosition(15f, 10f)
-        val beginPosition = PxPosition(30f, 20f)
+        val dragDistance = Offset(15f, 10f)
+        val beginPosition = Offset(30f, 20f)
 
         selection = fakeInitialSelection
         val result = selectionManager.longPressDragObserver.onDrag(dragDistance)
 
-        assertThat(result).isEqualTo(PxPosition.Origin)
+        assertThat(result).isEqualTo(Offset.Zero)
         verify(selectable, times(0))
             .getSelection(
                 startPosition = beginPosition,
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerTest.kt
index a56b8c1..b6888ed 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionManagerTest.kt
@@ -29,7 +29,7 @@
 import androidx.ui.text.length
 import androidx.ui.text.style.TextDirection
 import androidx.ui.text.subSequence
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.doReturn
@@ -60,8 +60,8 @@
     private val middleSelectable = mock<Selectable>()
     private val lastSelectable = mock<Selectable>()
 
-    private val startCoordinates = PxPosition(3f, 30f)
-    private val endCoordinates = PxPosition(3f, 600f)
+    private val startCoordinates = Offset(3f, 30f)
+    private val endCoordinates = Offset(3f, 600f)
 
     private val fakeSelection =
         Selection(
@@ -99,7 +99,7 @@
     @Test
     fun mergeSelections_sorting() {
         whenever((containerLayoutCoordinates.childToLocal(any(), any())))
-            .thenReturn(PxPosition.Origin)
+            .thenReturn(Offset.Zero)
 
         selectionManager.mergeSelections(
             startPosition = startCoordinates,
@@ -141,7 +141,7 @@
         val selectable_another = mock<Selectable>()
         selectionRegistrar.subscribe(selectable_another)
         whenever((containerLayoutCoordinates.childToLocal(any(), any())))
-            .thenReturn(PxPosition.Origin)
+            .thenReturn(Offset.Zero)
 
         selectionManager.mergeSelections(
             startPosition = startCoordinates,
@@ -416,8 +416,8 @@
 
         verify(selectable, times(1))
             .getSelection(
-                startPosition = PxPosition(-1f, -1f),
-                endPosition = PxPosition(-1f, -1f),
+                startPosition = Offset(-1f, -1f),
+                endPosition = Offset(-1f, -1f),
                 containerLayoutCoordinates = selectionManager.requireContainerCoordinates(),
                 longPress = false,
                 previousSelection = fakeSelection
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionRegistrarImplTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionRegistrarImplTest.kt
index 4188bb3..fb1db38 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionRegistrarImplTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/selection/SelectionRegistrarImplTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.whenever
@@ -75,19 +75,19 @@
         whenever(handler3.getLayoutCoordinates()).thenReturn(layoutCoordinates3)
 
         // The order of the 4 handlers should be 1, 0, 3, 2.
-        val relativeCoordinates0 = PxPosition(20f, 12f)
-        val relativeCoordinates1 = PxPosition(5f, 12f)
-        val relativeCoordinates2 = PxPosition(20f, 24f)
-        val relativeCoordinates3 = PxPosition(5f, 24f)
+        val relativeCoordinates0 = Offset(20f, 12f)
+        val relativeCoordinates1 = Offset(5f, 12f)
+        val relativeCoordinates2 = Offset(20f, 24f)
+        val relativeCoordinates3 = Offset(5f, 24f)
 
         val containerLayoutCoordinates = mock<LayoutCoordinates>()
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, Offset.Zero))
             .thenReturn(relativeCoordinates0)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates1, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates1, Offset.Zero))
             .thenReturn(relativeCoordinates1)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates2, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates2, Offset.Zero))
             .thenReturn(relativeCoordinates2)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates3, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates3, Offset.Zero))
             .thenReturn(relativeCoordinates3)
 
         val selectionRegistrar = SelectionRegistrarImpl()
@@ -126,19 +126,19 @@
         whenever(handler3.getLayoutCoordinates()).thenReturn(layoutCoordinates3)
 
         // The order of the 4 handlers should be 1, 0, 3, 2.
-        val relativeCoordinates0 = PxPosition(20f, 12f)
-        val relativeCoordinates1 = PxPosition(5f, 12f)
-        val relativeCoordinates2 = PxPosition(20f, 24f)
-        val relativeCoordinates3 = PxPosition(5f, 24f)
+        val relativeCoordinates0 = Offset(20f, 12f)
+        val relativeCoordinates1 = Offset(5f, 12f)
+        val relativeCoordinates2 = Offset(20f, 24f)
+        val relativeCoordinates3 = Offset(5f, 24f)
 
         val containerLayoutCoordinates = mock<LayoutCoordinates>()
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, Offset.Zero))
             .thenReturn(relativeCoordinates0)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates1, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates1, Offset.Zero))
             .thenReturn(relativeCoordinates1)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates2, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates2, Offset.Zero))
             .thenReturn(relativeCoordinates2)
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates3, PxPosition.Origin))
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates3, Offset.Zero))
             .thenReturn(relativeCoordinates3)
 
         val selectionRegistrar = SelectionRegistrarImpl()
@@ -165,8 +165,8 @@
         val layoutCoordinates0 = mock<LayoutCoordinates>()
         whenever(handler0.getLayoutCoordinates()).thenReturn(layoutCoordinates0)
         val containerLayoutCoordinates = mock<LayoutCoordinates>()
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, PxPosition.Origin))
-            .thenReturn(PxPosition.Origin)
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, Offset.Zero))
+            .thenReturn(Offset.Zero)
 
         val selectionRegistrar = SelectionRegistrarImpl()
         selectionRegistrar.subscribe(handler0)
@@ -187,8 +187,8 @@
         val layoutCoordinates0 = mock<LayoutCoordinates>()
         whenever(handler0.getLayoutCoordinates()).thenReturn(layoutCoordinates0)
         val containerLayoutCoordinates = mock<LayoutCoordinates>()
-        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, PxPosition.Origin))
-            .thenReturn(PxPosition.Origin)
+        whenever(containerLayoutCoordinates.childToLocal(layoutCoordinates0, Offset.Zero))
+            .thenReturn(Offset.Zero)
 
         val selectionRegistrar = SelectionRegistrarImpl()
         selectionRegistrar.subscribe(handler0)
diff --git a/ui/ui-desktop/README.md b/ui/ui-desktop/README.md
index 5bb4c07..c266f16 100644
--- a/ui/ui-desktop/README.md
+++ b/ui/ui-desktop/README.md
@@ -2,4 +2,4 @@
 
 To try:
 
-    ./gradlew -Pcompose.desktop=1 :ui:ui-desktop:run
\ No newline at end of file
+    ./gradlew -Pcompose.desktop=1 :ui:ui-desktop:samples:run
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
index 5be854f..33c7c9c 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
@@ -30,6 +30,10 @@
         skijaCanvas!!.translate(x, y)
     }
 
+    fun rotate(degrees: Float) {
+        skijaCanvas!!.rotate(degrees)
+    }
+
     fun drawLine(
         startX: Float,
         startY: Float,
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt
index 2ce6324..abef8f5 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt
@@ -17,9 +17,13 @@
 package android.graphics
 
 class Rect(
+    @kotlin.jvm.JvmField
     var left: Int,
+    @kotlin.jvm.JvmField
     var top: Int,
+    @kotlin.jvm.JvmField
     var right: Int,
+    @kotlin.jvm.JvmField
     var bottom: Int
 ) {
     constructor() : this(0, 0, 0, 0)
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/RectF.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/RectF.kt
index d2bf78d..5cf8bd4 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/RectF.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/RectF.kt
@@ -17,9 +17,13 @@
 package android.graphics
 
 class RectF(
+    @kotlin.jvm.JvmField
     var left: Float,
+    @kotlin.jvm.JvmField
     var top: Float,
+    @kotlin.jvm.JvmField
     var right: Float,
+    @kotlin.jvm.JvmField
     var bottom: Float
 ) {
     constructor() : this(0f, 0f, 0f, 0f)
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt
index 9b3aebe..f1bd952 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt
@@ -16,6 +16,10 @@
 
 package android.graphics
 
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.StandardCopyOption
+
 private const val NORMAL_FONT_NAME = "NotoSans-Regular"
 private const val BOLD_FONT_NAME = "NotoSans-Bold"
 private const val ITALIC_FONT_NAME = "NotoSans-Italic"
@@ -59,5 +63,15 @@
 }
 
 fun getFontPathAsString(font: String): String {
-    return Typeface::class.java.getClassLoader().getResource("$font.ttf").getFile()
+    val tempDir = File(System.getProperty("java.io.tmpdir"), "compose").apply {
+        mkdirs()
+        deleteOnExit()
+    }
+    val tempFile = File(tempDir, "$font.ttf").apply {
+        deleteOnExit()
+    }
+    val stream = Typeface::class.java.getClassLoader().getResourceAsStream("$font.ttf")
+    if (stream == null) throw Error("Cannoty find font $font")
+    Files.copy(stream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
+    return tempFile.absolutePath
 }
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
index f00473fb..28999e2 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
@@ -21,6 +21,8 @@
 public class Handler() {
     constructor(looper: Looper, callback: Handler.Callback) : this()
 
+    constructor(looper: Looper, callback: Callback, async: Boolean) : this()
+
     interface Callback {
         fun handleMessage(msg: Message): Boolean
     }
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt
index dea489c..ef23d80 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt
@@ -85,6 +85,8 @@
             val accessibility_custom_action_30 = 30
             @JvmField
             val accessibility_custom_action_31 = 31
+            @JvmField
+            var inspection_slot_table_set = 0
         }
     }
 }
diff --git a/ui/ui-desktop/build.gradle b/ui/ui-desktop/build.gradle
index 0b7d652..7f261bc 100644
--- a/ui/ui-desktop/build.gradle
+++ b/ui/ui-desktop/build.gradle
@@ -147,11 +147,9 @@
         "ui-livedata",
         "ui-material",
         "ui-saved-instance-state",
-        "ui-test",
         "ui-text",
         "ui-text-android",
         "ui-text-core",
-        "ui-tooling",
         "ui-unit",
         "ui-util",
         "ui-vector"
@@ -162,10 +160,8 @@
         "lifecycle:lifecycle-runtime"
 ]
 
-
 def copyToJar(File source, File jar) {
-
-    if(source.name.endsWith(".jar")) {
+    if (source.name.endsWith(".jar")) {
         Files.copy(source.toPath(), jar.toPath(), StandardCopyOption.REPLACE_EXISTING)
         return
     }
@@ -248,27 +244,30 @@
             } else {
                 def destJar = composeClassDir + component + ".jar"
                 Files.copy(Paths.get(srcJar), Paths.get(destJar), StandardCopyOption.REPLACE_EXISTING)
-                // TODO: restore missing kotlin_module and remove this code.
-                def missingModuleDir = findInDeps(task, { absolutePath ->
-                    absolutePath.indexOf("kotlin-classes/release") != -1
-                })
-                if (missingModuleDir == null)
-                    throw new Error("cannot find build dir")
-                def shortName = "META-INF/" + component + "_release.kotlin_module"
-                def missingModule = missingModuleDir + "/" + shortName
-                addToJar(destJar, shortName, missingModule)
             }
         }
-        def frameworkProject = project(":compose:compose-compiler")
-        def srcJar = findInDeps(frameworkProject.tasks.named("assemble").get(), {
+        // Compose compiler plugin build does ugly renaming tricks, so find the proper jar.
+        def compilerProject = project(":compose:compose-compiler")
+        def compilerJar = findInDeps(compilerProject.tasks.named("embeddedPlugin").get(), {
             absolutePath ->
-            Pattern.matches(".*/compose-compiler.*.jar", absolutePath)
+            println(absolutePath)
+            Pattern.matches(".*/jarjar/compose-compiler.jar", absolutePath)
         })
-        if (srcJar == null)
+        if (compilerJar == null)
             throw new Error("cannot find compose-compiler.jar")
-        Files.copy(Paths.get(srcJar),
+        Files.copy(Paths.get(compilerJar),
                 Paths.get(composeClassDir + "compose-compiler.jar"), StandardCopyOption.REPLACE_EXISTING)
 
+        def runtimeProject = project(":compose:compose-runtime")
+        def runtimeJar = findInDeps(runtimeProject.tasks.named("assemble").get(), {
+            absolutePath ->
+            Pattern.matches(".*/compose-runtime-desktop.*.jar", absolutePath)
+        })
+        if (runtimeJar == null)
+            throw new Error("cannot find compose-runtime.jar")
+        Files.copy(Paths.get(runtimeJar),
+                Paths.get(composeClassDir + "compose-runtime.jar"), StandardCopyOption.REPLACE_EXISTING)
+
         configurations.ui_components.getIncoming().artifactView(
                 { config ->
                     config.attributes({container ->
@@ -294,20 +293,15 @@
     dependsOn("extractJars")
     kotlinOptions {
         useIR = true
-        jvmTarget = "1.8"
-        freeCompilerArgs += [
-                // TODO: hack, apply compose plugin better.
-                "-Xplugin=${project.rootDir.absolutePath}/ui-desktop/compose-libs/compose-compiler.jar",
-                "-P", "plugin:androidx.compose.plugins.idea:enabled=true",
-
-        ]
     }
 }
 
-task run(type: JavaExec) {
-    main = 'androidx.ui.desktop.example.MainKt'
-    jvmArgs += '-Dkotlinx.coroutines.fast.service.loader=false'
-    def compilation = kotlin.jvm().compilations["main"]
-    classpath = compilation.output.allOutputs + compilation.runtimeDependencyFiles +
-            fileTree(composeClassDir)
+task desktopJar(type: Jar) {
+    baseName = "ui-desktop"
+    from { kotlin.jvm().compilations["main"].output.allOutputs }
+    destinationDir file(composeClassDir)
 }
+
+clean.doFirst {
+    delete composeClassDir
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/samples/build.gradle b/ui/ui-desktop/samples/build.gradle
new file mode 100644
index 0000000..d0cb4e0
--- /dev/null
+++ b/ui/ui-desktop/samples/build.gradle
@@ -0,0 +1,71 @@
+/*
+ * 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 org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("AndroidXUiPlugin")
+    id("kotlin-multiplatform")
+}
+
+dependencies {
+    kotlinPlugin project(path: ":compose:compose-compiler")
+}
+
+def sdkDir = project.rootDir.absolutePath + "/ui-desktop/compose-libs/"
+
+kotlin {
+    jvm()
+
+    sourceSets {
+        jvmMain.dependencies {
+            implementation project(":ui:ui-desktop")
+            implementation fileTree(sdkDir)
+        }
+    }
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        useIR = true
+    }
+}
+
+task run1(type: JavaExec) {
+    dependsOn(":ui:ui-desktop:desktopJar")
+    main = 'androidx.ui.desktop.examples.example1.MainKt'
+    def compilation = kotlin.jvm().compilations["main"]
+    classpath =
+        compilation.output.allOutputs +
+        compilation.runtimeDependencyFiles +
+        fileTree(sdkDir)
+}
+
+task run2(type: JavaExec) {
+    dependsOn(":ui:ui-desktop:desktopJar")
+    main = 'androidx.ui.desktop.examples.example2.MainKt'
+    def compilation = kotlin.jvm().compilations["main"]
+    classpath =
+        compilation.output.allOutputs +
+        compilation.runtimeDependencyFiles +
+        fileTree(sdkDir)
+}
+
+task run {
+    dependsOn("run1")
+}
diff --git a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/Common.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/Common.kt
new file mode 100644
index 0000000..9e347e5
--- /dev/null
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/Common.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.desktop.examples
+
+import androidx.compose.Composable
+import androidx.ui.desktop.SkiaWindow
+import androidx.ui.desktop.setContent
+
+import javax.swing.WindowConstants
+
+fun mainWith(title: String, app: @Composable () -> Unit) {
+    val width = 1024
+    val height = 768
+
+    val frame = SkiaWindow(width = width, height = height)
+
+    frame.title = title
+    frame.setLocation(400, 400)
+    frame.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
+
+    frame.setContent {
+        app()
+    }
+
+    frame.setVisible(true)
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
similarity index 81%
rename from ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt
rename to ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
index b6bd8d1..afaa8ac 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
@@ -13,15 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package androidx.ui.desktop.example
+package androidx.ui.desktop.examples.example1
 
 import androidx.compose.Composable
 import androidx.compose.state
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
 import androidx.ui.graphics.Color
-import androidx.ui.desktop.SkiaWindow
-import androidx.ui.desktop.setContent
 import androidx.ui.foundation.Text
 import androidx.ui.foundation.drawBackground
 import androidx.ui.layout.Arrangement
@@ -38,31 +36,15 @@
 import androidx.ui.material.TopAppBar
 import androidx.ui.unit.dp
 
-import javax.swing.WindowConstants
+import androidx.ui.desktop.examples.mainWith
 
-fun main() {
-    val width = 1024
-    val height = 768
+private const val title = "Desktop Compose Elements"
 
-    val frame = SkiaWindow(width = width, height = height)
-
-    frame.title = "Skija Demo"
-    frame.setLocation(400, 400)
-    frame.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
-
-    frame.setContent {
-        App()
-    }
-
-    frame.setVisible(true)
-}
-
-@Composable
-fun App() {
+fun main() = mainWith(title) @Composable {
     Scaffold(
-        topAppBar = {
+        topBar = {
             TopAppBar(
-                title = { Text("Desktop Compose") }
+                title = { Text(title) }
             )
         },
         floatingActionButton = {
@@ -73,10 +55,10 @@
                 }
             )
         },
-        bodyContent = { modifier ->
+        bodyContent = {
             val amount = state { 0 }
             val text = state { "Hello" }
-            Column(modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
+            Column(Modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
                 Text(
                     text = "Привет! 你好! Desktop Compose ${amount.value}",
                     color = Color.Black,
diff --git a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt
new file mode 100644
index 0000000..904d29e
--- /dev/null
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.desktop.examples.example2
+
+import androidx.compose.Composable
+import androidx.ui.core.Modifier
+import androidx.ui.foundation.Canvas
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.Stroke
+import androidx.ui.graphics.drawscope.inset
+import androidx.ui.graphics.drawscope.rotate
+import androidx.ui.graphics.drawscope.withTransform
+import androidx.ui.layout.preferredSize
+import androidx.ui.unit.dp
+
+import androidx.ui.desktop.examples.mainWith
+
+private const val title = "Desktop Compose Canvas"
+
+fun main() = mainWith(title) @Composable {
+    val width = 1024
+    Canvas(modifier = Modifier.preferredSize(width.dp)) {
+        drawRect(Color.Magenta)
+        inset(10.0f) {
+            drawLine(
+                p1 = Offset.zero,
+                p2 = Offset(size.width, size.height),
+                stroke = Stroke(width = 5.0f),
+                color = Color.Red
+            )
+        }
+        floatArrayOf(0.3f, 0.7f, 1.3f).forEach {
+            withTransform({
+                translate(10.0f, 12.0f)
+                rotate(45f * it)
+                scale(it, 1f / it)
+            }) {
+                drawRect(Color(0f, 0f, 1f, it / 2f))
+                drawCircle(Color(1f, 0f, 0f, it / 2f))
+            }
+        }
+    }
+}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
index a019493..3a03df4 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
@@ -77,6 +77,9 @@
     companion object {
         init {
             JNI.loadLibrary("/", "skija")
+            // Until https://github.com/Kotlin/kotlinx.coroutines/issues/2039 is resolved
+            // we have to set this property manually for coroutines to work.
+            System.getProperties().setProperty("kotlinx.coroutines.fast.service.loader", "false")
         }
     }
 
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
index 57ace89..7573dae 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
@@ -33,6 +33,7 @@
 
 import org.jetbrains.skija.Canvas
 
+@OptIn(androidx.animation.InternalAnimationApi::class)
 fun SkiaWindow.setContent(content: @Composable () -> Unit) {
     SwingUtilities.invokeLater {
         val fps = 60
diff --git a/ui/ui-foundation/api/0.1.0-dev14.txt b/ui/ui-foundation/api/0.1.0-dev14.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/0.1.0-dev14.txt
+++ b/ui/ui-foundation/api/0.1.0-dev14.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev14.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev14.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev14.txt b/ui/ui-foundation/api/restricted_0.1.0-dev14.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev14.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 99e1bb8..61e4cf7 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -115,10 +115,10 @@
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
     ctor public InteractionState();
-    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.unit.PxPosition? position = null);
+    method public void addInteraction(androidx.ui.foundation.Interaction interaction, androidx.ui.geometry.Offset? position = null);
     method public operator boolean contains(androidx.ui.foundation.Interaction interaction);
     method public java.util.Set<androidx.ui.foundation.Interaction> getValue();
-    method public androidx.ui.unit.PxPosition? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
+    method public androidx.ui.geometry.Offset? interactionPositionFor(androidx.ui.foundation.Interaction interaction);
     method public void removeInteraction(androidx.ui.foundation.Interaction interaction);
     property public java.util.Set<androidx.ui.foundation.Interaction> value;
   }
@@ -284,12 +284,12 @@
   }
 
   public final class DraggableKt {
-    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
+    method public static androidx.ui.core.Modifier draggable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onDragStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onDragStopped = {}, boolean enabled = true, androidx.ui.foundation.InteractionState? interactionState = null, boolean startDragImmediately = false, kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onDragDeltaConsumptionRequested);
   }
 
   public final class ScrollableKt {
     method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ScrollableState ScrollableState(kotlin.jvm.functions.Function1<? super java.lang.Float,java.lang.Float> onScrollDeltaConsumptionRequested);
-    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.unit.PxPosition,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
+    method public static androidx.ui.core.Modifier scrollable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.DragDirection dragDirection, androidx.ui.foundation.gestures.ScrollableState scrollableState, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onScrollStarted = {}, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onScrollStopped = {}, boolean enabled = true);
   }
 
   public final class ScrollableState {
@@ -302,6 +302,18 @@
     property public final boolean isAnimating;
   }
 
+  public final class ZoomableKt {
+    method @androidx.compose.Composable public static androidx.ui.foundation.gestures.ZoomableState ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, androidx.ui.foundation.gestures.ZoomableState zoomableState, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null);
+    method @androidx.compose.Composable public static androidx.ui.core.Modifier zoomable(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit>? onZoomStopped = null, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta);
+  }
+
+  public final class ZoomableState {
+    ctor public ZoomableState(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onZoomDelta, androidx.animation.AnimationClockObservable animationClock);
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit> getOnZoomDelta();
+    method public void smoothScaleBy(float value, kotlin.jvm.functions.Function2<? super androidx.animation.AnimationEndReason,? super java.lang.Float,kotlin.Unit>? onEnd = null);
+  }
+
 }
 
 package androidx.ui.foundation.selection {
diff --git a/ui/ui-foundation/integration-tests/foundation-demos/src/main/java/androidx/ui/foundation/demos/FoundationDemos.kt b/ui/ui-foundation/integration-tests/foundation-demos/src/main/java/androidx/ui/foundation/demos/FoundationDemos.kt
index 5112247..611f492 100644
--- a/ui/ui-foundation/integration-tests/foundation-demos/src/main/java/androidx/ui/foundation/demos/FoundationDemos.kt
+++ b/ui/ui-foundation/integration-tests/foundation-demos/src/main/java/androidx/ui/foundation/demos/FoundationDemos.kt
@@ -22,11 +22,13 @@
 import androidx.ui.foundation.samples.DialogSample
 import androidx.ui.foundation.samples.InteractionStateSample
 import androidx.ui.foundation.samples.VerticalScrollerSample
+import androidx.ui.foundation.samples.ZoomableSample
 
 val FoundationDemos = DemoCategory("Foundation", listOf(
     ComposableDemo("Draggable and Scrollable") { HighLevelGesturesDemo() },
     ComposableDemo("VerticalScroller") { VerticalScrollerSample() },
     ComposableDemo("HorizontalScroller") { ControlledHorizontalScrollerSample() },
+    ComposableDemo("Zoomable") { ZoomableSample() },
     ComposableDemo("Dialog") { DialogSample() },
     ComposableDemo("Draw Modifiers") { DrawModifiersDemo() },
     ComposableDemo("Boxes") { BoxDemo() },
diff --git a/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/CanvasSamples.kt b/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/CanvasSamples.kt
index c1bff5a1..4cff560 100644
--- a/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/CanvasSamples.kt
+++ b/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/CanvasSamples.kt
@@ -34,7 +34,7 @@
         drawRect(Color.Magenta)
         inset(10.0f) {
             drawLine(
-                p1 = Offset.zero,
+                p1 = Offset.Zero,
                 p2 = Offset(size.width, size.height),
                 stroke = Stroke(width = 5.0f),
                 color = Color.Red
diff --git a/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/ZoomableSample.kt b/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/ZoomableSample.kt
new file mode 100644
index 0000000..2efe08c
--- /dev/null
+++ b/ui/ui-foundation/samples/src/main/java/androidx/ui/foundation/samples/ZoomableSample.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.foundation.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.Composable
+import androidx.compose.StructurallyEqual
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.compose.state
+import androidx.ui.core.Modifier
+import androidx.ui.core.clipToBounds
+import androidx.ui.core.drawLayer
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.ContentGravity
+import androidx.ui.foundation.Text
+import androidx.ui.foundation.clickable
+import androidx.ui.foundation.drawBorder
+import androidx.ui.foundation.gestures.ZoomableState
+import androidx.ui.foundation.gestures.zoomable
+import androidx.ui.graphics.Color
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.preferredSize
+import androidx.ui.unit.dp
+import androidx.ui.unit.sp
+
+@Sampled
+@Composable
+fun ZoomableSample() {
+    Box(
+        Modifier.preferredSize(700.dp).clipToBounds(),
+        backgroundColor = Color.LightGray
+    ) {
+        var scale by state(StructurallyEqual) { 1f }
+        val zoomableState = ZoomableState { scale *= it }
+
+        Box(
+            Modifier
+                .zoomable(zoomableState)
+                .clickable(
+                    indication = null,
+                    onDoubleClick = { zoomableState.smoothScaleBy(4f) },
+                    onClick = {}
+                )
+                .fillMaxSize()
+                .drawBorder(1.dp, Color.Green),
+            gravity = ContentGravity.Center
+        ) {
+            Text(
+                "☠",
+                fontSize = 32.sp,
+                modifier = Modifier.drawLayer(scaleX = scale, scaleY = scale)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/AdapterListTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/AdapterListTest.kt
index 346189c..c2df4da 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/AdapterListTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/AdapterListTest.kt
@@ -19,6 +19,7 @@
 import androidx.compose.getValue
 import androidx.compose.mutableStateOf
 import androidx.compose.onCommit
+import androidx.compose.onDispose
 import androidx.compose.setValue
 import androidx.test.filters.LargeTest
 import androidx.ui.core.Modifier
@@ -26,6 +27,7 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.height
 import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.size
 import androidx.ui.semantics.Semantics
 import androidx.ui.semantics.testTag
 import androidx.ui.test.assertCountEquals
@@ -161,6 +163,46 @@
     }
 
     @Test
+    fun compositionsAreDisposed_whenAdapterListIsDisposed() {
+        var emitAdapterList by mutableStateOf(true)
+        var disposeCalledOnFirstItem = false
+        var disposeCalledOnSecondItem = false
+
+        composeTestRule.setContent {
+            if (emitAdapterList) {
+                AdapterList(
+                    data = listOf(0, 1),
+                    modifier = Modifier.fillMaxSize()
+                ) {
+                    Box(Modifier.size(100.dp))
+                    onDispose {
+                        if (it == 1) {
+                            disposeCalledOnFirstItem = true
+                        } else {
+                            disposeCalledOnSecondItem = true
+                        }
+                    }
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            assertWithMessage("First item is not immediately disposed")
+                .that(disposeCalledOnFirstItem).isFalse()
+            assertWithMessage("Second item is not immediately disposed")
+                .that(disposeCalledOnFirstItem).isFalse()
+            emitAdapterList = false
+        }
+
+        runOnIdleCompose {
+            assertWithMessage("First item is correctly disposed")
+                .that(disposeCalledOnFirstItem).isTrue()
+            assertWithMessage("Second item is correctly disposed")
+                .that(disposeCalledOnSecondItem).isTrue()
+        }
+    }
+
+    @Test
     fun removeItemsTest() {
         val startingNumItems = 3
         var numItems = startingNumItems
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 34ac07a..246d264 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
@@ -42,9 +42,8 @@
 import androidx.ui.test.findByTag
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
-import androidx.ui.unit.ipx
 import com.google.common.truth.Truth
 import org.junit.Rule
 import org.junit.Test
@@ -83,7 +82,7 @@
     @Test
     fun box_testPadding_separate() {
         var childSize: IntPxSize? = null
-        var childPosition: PxPosition? = null
+        var childPosition: Offset? = null
         val size = 100.dp
         val start = 17.dp
         val top = 2.dp
@@ -100,7 +99,7 @@
                 ) {
                     Box(Modifier.fillMaxSize().onPositioned {
                         childSize = it.size
-                        childPosition = it.localToGlobal(PxPosition.Origin)
+                        childPosition = it.localToGlobal(Offset.Zero)
                     })
                 }
             }
@@ -112,14 +111,14 @@
             Truth.assertThat(childSize!!.height)
                 .isEqualTo(size.toIntPx() - top.toIntPx() - bottom.toIntPx())
             Truth.assertThat(childPosition!!)
-                .isEqualTo(PxPosition(start.toIntPx(), top.toIntPx()))
+                .isEqualTo(Offset(start.toIntPx().value.toFloat(), top.toIntPx().value.toFloat()))
         }
     }
 
     @Test
     fun box_testPadding_rtl() {
         var childSize: IntPxSize? = null
-        var childPosition: PxPosition? = null
+        var childPosition: Offset? = null
         val size = 100.dp
         val start = 17.dp
         val top = 2.dp
@@ -136,7 +135,7 @@
                 ) {
                     Box(Modifier.fillMaxSize().onPositioned {
                         childSize = it.size
-                        childPosition = it.localToGlobal(PxPosition.Origin)
+                        childPosition = it.localToGlobal(Offset.Zero)
                     })
                 }
             }
@@ -148,7 +147,7 @@
             Truth.assertThat(childSize!!.height)
                 .isEqualTo(size.toIntPx() - top.toIntPx() - bottom.toIntPx())
             Truth.assertThat(childPosition!!)
-                .isEqualTo(PxPosition(end.toIntPx(), top.toIntPx()))
+                .isEqualTo(Offset(end.toIntPx().value.toFloat(), top.toIntPx().value.toFloat()))
         }
     }
 
@@ -186,9 +185,9 @@
     fun box_testLayout_multipleChildren() {
         val size = 100.dp
         val childSize = 20.dp
-        var childPosition1: PxPosition? = null
-        var childPosition2: PxPosition? = null
-        var childPosition3: PxPosition? = null
+        var childPosition1: Offset? = null
+        var childPosition2: Offset? = null
+        var childPosition3: Offset? = null
         composeTestRule.setContent {
             SemanticsParent {
                 Box(
@@ -209,21 +208,21 @@
         }
         with(composeTestRule.density) {
             Truth.assertThat(childPosition1).isEqualTo(
-                PxPosition(
-                    (size.toIntPx() - childSize.toIntPx()) / 2,
-                    0.ipx
+                Offset(
+                    (size.toIntPx() - childSize.toIntPx()).value / 2f,
+                    0f
                 )
             )
             Truth.assertThat(childPosition2).isEqualTo(
-                PxPosition(
-                    (size.toIntPx() - childSize.toIntPx()) / 2,
-                    childSize.toIntPx()
+                Offset(
+                    (size.toIntPx() - childSize.toIntPx()).value / 2f,
+                    childSize.toIntPx().value.toFloat()
                 )
             )
             Truth.assertThat(childPosition3).isEqualTo(
-                PxPosition(
-                    (size.toIntPx() - childSize.toIntPx()) / 2,
-                    childSize.toIntPx() * 2
+                Offset(
+                    (size.toIntPx() - childSize.toIntPx()).value / 2f,
+                    childSize.toIntPx().value.toFloat() * 2
                 )
             )
         }
@@ -233,7 +232,7 @@
     fun box_testLayout_absoluteAlignment() {
         val size = 100.dp
         val childSize = 20.dp
-        var childPosition: PxPosition? = null
+        var childPosition: Offset? = null
         composeTestRule.setContent {
             SemanticsParent {
                 Box(
@@ -246,7 +245,7 @@
                 }
             }
         }
-        Truth.assertThat(childPosition).isEqualTo(PxPosition(0.ipx, 0.ipx))
+        Truth.assertThat(childPosition).isEqualTo(Offset(0f, 0f))
     }
 
     @Test
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 5a340a6..35466f2 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
@@ -79,7 +79,7 @@
                 .wrapContentSize(Alignment.Center)) {
                     Canvas(modifier = Modifier.preferredSize(minWidth, minHeight)) {
                         drawLine(
-                            p1 = Offset.zero,
+                            p1 = Offset.Zero,
                             p2 = Offset(size.width, size.height),
                             color = Color.Red,
                             stroke = Stroke(width = strokeWidth)
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DraggableTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DraggableTest.kt
index 59e5574..4d9fff49 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DraggableTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DraggableTest.kt
@@ -34,7 +34,7 @@
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendSwipe
 import androidx.ui.test.sendSwipeWithVelocity
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -67,7 +67,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -78,7 +78,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y + 100f),
+                end = Offset(this.center.x, this.center.y + 100f),
                 duration = 100.milliseconds
             )
         }
@@ -88,7 +88,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x - 100f, this.center.y),
+                end = Offset(this.center.x - 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -112,7 +112,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y + 100f),
+                end = Offset(this.center.x, this.center.y + 100f),
                 duration = 100.milliseconds
             )
         }
@@ -123,7 +123,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -133,7 +133,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y - 100f),
+                end = Offset(this.center.x, this.center.y - 100f),
                 duration = 100.milliseconds
             )
         }
@@ -167,7 +167,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -194,7 +194,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -206,7 +206,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -232,7 +232,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipeWithVelocity(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 endVelocity = 112f,
                 duration = 100.milliseconds
 
@@ -259,7 +259,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -289,7 +289,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -332,7 +332,7 @@
         findByTag(draggableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 200f, this.center.y),
+                end = Offset(this.center.x + 200f, this.center.y),
                 duration = 300.milliseconds
             )
         }
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DrawBackgroundTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DrawBackgroundTest.kt
index ab1a9f2..81cd2ad 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DrawBackgroundTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/DrawBackgroundTest.kt
@@ -34,7 +34,6 @@
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.findByTag
 import androidx.ui.unit.Density
-import androidx.ui.unit.px
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -55,10 +54,10 @@
         composeTestRule.setContent {
             SemanticParent {
                 Box(
-                    Modifier.preferredSize(40.px.toDp()).drawBackground(Color.Magenta),
+                    Modifier.preferredSize(40f.toDp()).drawBackground(Color.Magenta),
                     gravity = ContentGravity.Center
                 ) {
-                    Box(Modifier.preferredSize(20.px.toDp()).drawBackground(Color.White))
+                    Box(Modifier.preferredSize(20f.toDp()).drawBackground(Color.White))
                 }
             }
         }
@@ -78,11 +77,11 @@
         composeTestRule.setContent {
             SemanticParent {
                 Box(
-                    Modifier.preferredSize(40.px.toDp()).drawBackground(Color.Magenta),
+                    Modifier.preferredSize(40f.toDp()).drawBackground(Color.Magenta),
                     gravity = ContentGravity.Center
                 ) {
                     Box(
-                        Modifier.preferredSize(20.px.toDp())
+                        Modifier.preferredSize(20f.toDp())
                             .drawBackground(SolidColor(Color.White))
                     )
                 }
@@ -104,7 +103,7 @@
         composeTestRule.setContent {
             SemanticParent {
                 Box(
-                    Modifier.preferredSize(40.px.toDp())
+                    Modifier.preferredSize(40f.toDp())
                         .drawBackground(Color.Magenta)
                         .drawBackground(color = Color.White, shape = CircleShape)
                 )
@@ -125,7 +124,7 @@
         composeTestRule.setContent {
             SemanticParent {
                 Box(
-                    Modifier.preferredSize(40.px.toDp())
+                    Modifier.preferredSize(40f.toDp())
                         .drawBackground(Color.Magenta)
                         .drawBackground(
                             brush = SolidColor(Color.White),
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/IndicationTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/IndicationTest.kt
index 993dbb0..acd9946 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/IndicationTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/IndicationTest.kt
@@ -29,7 +29,7 @@
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendDown
 import androidx.ui.test.sendUp
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import com.google.common.truth.Truth.assertThat
 import org.junit.Ignore
@@ -123,7 +123,7 @@
     @Test
     @Ignore("b/155466122: multitouch is not supported yet")
     fun indication_multiplyPress_firstWins() {
-        var lastPosition: PxPosition? = null
+        var lastPosition: Offset? = null
         val indication = makeIndication {
             it.value // value read
             lastPosition = it.interactionPositionFor(Interaction.Pressed)
@@ -136,11 +136,11 @@
             )
         }
         assertThat(lastPosition).isNull()
-        var position1: PxPosition? = null
+        var position1: Offset? = null
         findByTag(testTag)
             .assertExists()
             .doPartialGesture {
-                position1 = PxPosition(center.x, center.y + 20f)
+                position1 = Offset(center.x, center.y + 20f)
                 // pointer 1, when we have multitouch
                 sendDown(position1!!)
             }
@@ -150,7 +150,7 @@
         findByTag(testTag)
             .assertExists()
             .doPartialGesture {
-                val position2 = PxPosition(center.x + 20f, center.y)
+                val position2 = Offset(center.x + 20f, center.y)
                 // pointer 2, when we have multitouch
                 sendDown(position2)
             }
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollableTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollableTest.kt
index 3ebd1a0a..8795598 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollableTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ScrollableTest.kt
@@ -41,7 +41,7 @@
 import androidx.ui.test.runOnUiThread
 import androidx.ui.test.sendSwipe
 import androidx.ui.test.sendSwipeWithVelocity
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth
@@ -83,7 +83,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -96,7 +96,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y + 100f),
+                end = Offset(this.center.x, this.center.y + 100f),
                 duration = 100.milliseconds
             )
         }
@@ -108,7 +108,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x - 100f, this.center.y),
+                end = Offset(this.center.x - 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -139,7 +139,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y + 100f),
+                end = Offset(this.center.x, this.center.y + 100f),
                 duration = 100.milliseconds
             )
         }
@@ -152,7 +152,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -164,7 +164,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x, this.center.y - 100f),
+                end = Offset(this.center.x, this.center.y - 100f),
                 duration = 100.milliseconds
             )
         }
@@ -203,7 +203,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -243,7 +243,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -256,7 +256,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -291,7 +291,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipeWithVelocity(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 endVelocity = 112f,
                 duration = 100.milliseconds
 
@@ -302,7 +302,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipeWithVelocity(
                 start = this.center,
-                end = PxPosition(this.center.x - 100f, this.center.y),
+                end = Offset(this.center.x - 100f, this.center.y),
                 endVelocity = 312f,
                 duration = 100.milliseconds
 
@@ -335,7 +335,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100f, this.center.y),
+                end = Offset(this.center.x + 100f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -347,7 +347,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 114f, this.center.y),
+                end = Offset(this.center.x + 114f, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -387,7 +387,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 100, this.center.y),
+                end = Offset(this.center.x + 100, this.center.y),
                 duration = 100.milliseconds
             )
         }
@@ -550,7 +550,7 @@
         findByTag(scrollableBoxTag).doGesture {
             this.sendSwipe(
                 start = this.center,
-                end = PxPosition(this.center.x + 200f, this.center.y),
+                end = Offset(this.center.x + 200f, this.center.y),
                 duration = 300.milliseconds
             )
         }
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldOnValueChangeTextFieldValueTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
index 150bcaa..4a5ab4d 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
@@ -36,7 +36,7 @@
 import androidx.ui.test.runOnUiThread
 import androidx.ui.test.sendClick
 import androidx.ui.text.TextRange
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.argumentCaptor
@@ -94,7 +94,7 @@
 
         // Perform click to focus in.
         find(hasInputMethodsSupport())
-            .doGesture { sendClick(PxPosition(1f, 1f)) }
+            .doGesture { sendClick(Offset(1f, 1f)) }
 
         runOnIdleCompose {
             // Verify startInput is called and capture the callback.
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ZoomableTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ZoomableTest.kt
new file mode 100644
index 0000000..37bc291
--- /dev/null
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/ZoomableTest.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.foundation
+
+import androidx.compose.Composable
+import androidx.test.filters.SmallTest
+import androidx.ui.core.Modifier
+import androidx.ui.core.testTag
+import androidx.ui.foundation.gestures.ZoomableState
+import androidx.ui.foundation.gestures.zoomable
+import androidx.ui.geometry.Offset
+import androidx.ui.layout.preferredSize
+import androidx.ui.test.AnimationClockTestRule
+import androidx.ui.test.center
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.doGesture
+import androidx.ui.test.findByTag
+import androidx.ui.test.runOnIdleCompose
+import androidx.ui.test.runOnUiThread
+import androidx.ui.test.sendPinch
+import androidx.ui.test.size
+import androidx.ui.unit.dp
+import androidx.ui.unit.toPxSize
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+private const val TEST_TAG = "zoomableTestTag"
+
+private const val EDGE_FUZZ_FACTOR = 0.2f
+
+@SmallTest
+@RunWith(JUnit4::class)
+class ZoomableTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val clockRule = AnimationClockTestRule()
+
+    @Test
+    fun zoomable_zoomIn() {
+        var cumulativeScale = 1.0f
+        val state = ZoomableState(
+            onZoomDelta = { cumulativeScale *= it },
+            animationClock = clockRule.clock
+        )
+
+        setZoomableContent { Modifier.zoomable(state) }
+
+        findByTag(TEST_TAG).doGesture {
+            val leftStartX = center.x - 10
+            val leftEndX = size.toPxSize().width * EDGE_FUZZ_FACTOR
+            val rightStartX = center.x + 10
+            val rightEndX = size.toPxSize().width * (1 - EDGE_FUZZ_FACTOR)
+
+            sendPinch(
+                Offset(leftStartX, center.y),
+                Offset(leftEndX, center.y),
+                Offset(rightStartX, center.y),
+                Offset(rightEndX, center.y)
+            )
+        }
+
+        clockRule.advanceClock(milliseconds = 1000)
+
+        runOnIdleCompose {
+            assertWithMessage("Should have scaled at least 4x").that(cumulativeScale).isAtLeast(4f)
+        }
+    }
+
+    @Test
+    fun zoomable_zoomOut() {
+        var cumulativeScale = 1.0f
+        val state = ZoomableState(
+            onZoomDelta = { cumulativeScale *= it },
+            animationClock = clockRule.clock
+        )
+
+        setZoomableContent { Modifier.zoomable(state) }
+
+        findByTag(TEST_TAG).doGesture {
+            val leftStartX = size.toPxSize().width * EDGE_FUZZ_FACTOR
+            val leftEndX = center.x - 10
+            val rightStartX = size.toPxSize().width * (1 - EDGE_FUZZ_FACTOR)
+            val rightEndX = center.x + 10
+
+            sendPinch(
+                Offset(leftStartX, center.y),
+                Offset(leftEndX, center.y),
+                Offset(rightStartX, center.y),
+                Offset(rightEndX, center.y)
+            )
+        }
+
+        clockRule.advanceClock(milliseconds = 1000)
+
+        runOnIdleCompose {
+            assertWithMessage("Should have scaled down at least 4x")
+                .that(cumulativeScale)
+                .isAtMost(0.25f)
+        }
+    }
+
+    @Test
+    fun zoomable_animateTo() {
+        var cumulativeScale = 1.0f
+        var callbackCount = 0
+        val state = ZoomableState(
+            onZoomDelta = {
+                cumulativeScale *= it
+                callbackCount += 1
+            },
+            animationClock = clockRule.clock
+        )
+
+        setZoomableContent { Modifier.zoomable(state) }
+
+        runOnUiThread { state.smoothScaleBy(4f) }
+
+        clockRule.advanceClock(milliseconds = 10)
+
+        runOnIdleCompose {
+            assertWithMessage("Scrolling should have been smooth").that(callbackCount).isAtLeast(1)
+        }
+
+        clockRule.advanceClock(milliseconds = 10)
+
+        runOnIdleCompose {
+            assertWithMessage("Scrolling should have been smooth").that(callbackCount).isAtLeast(2)
+        }
+
+        clockRule.advanceClock(milliseconds = 1000)
+
+        runOnIdleCompose {
+            assertWithMessage("Scrolling should have been smooth").that(callbackCount).isAtLeast(3)
+            assertWithMessage("Should have scaled at least 4x").that(cumulativeScale).isAtLeast(4f)
+        }
+    }
+
+    private fun setZoomableContent(getModifier: @Composable () -> Modifier) {
+        composeTestRule.setContent {
+            Box(Modifier.preferredSize(600.dp).testTag(TEST_TAG) + getModifier())
+        }
+    }
+}
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/shape/corner/RoundedCornerShapeTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/shape/corner/RoundedCornerShapeTest.kt
index 775a5b2..17c187e 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/shape/corner/RoundedCornerShapeTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/shape/corner/RoundedCornerShapeTest.kt
@@ -42,7 +42,7 @@
     fun roundedUniformCorners() {
         val rounded = RoundedCornerShape(25)
 
-        val expectedRadius = Radius.circular(25f)
+        val expectedRadius = Radius(25f)
         val outline = rounded.toOutline() as Outline.Rounded
         assertThat(outline.rrect).isEqualTo(
             RRect(
@@ -63,10 +63,10 @@
         assertThat(outline.rrect).isEqualTo(
             RRect(
                 size.toRect(),
-                Radius.circular(radius1),
-                Radius.circular(radius2),
-                Radius.circular(radius3),
-                Radius.circular(radius4)
+                Radius(radius1),
+                Radius(radius2),
+                Radius(radius3),
+                Radius(radius4)
             )
         )
     }
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/AdapterList.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/AdapterList.kt
index 08127a7..cee692b 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/AdapterList.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/AdapterList.kt
@@ -25,6 +25,7 @@
 import androidx.compose.Untracked
 import androidx.compose.compositionReference
 import androidx.compose.currentComposer
+import androidx.compose.onDispose
 import androidx.compose.remember
 import androidx.ui.core.Constraints
 import androidx.ui.core.ContextAmbient
@@ -43,10 +44,9 @@
 import androidx.ui.foundation.gestures.scrollable
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
-import androidx.ui.unit.round
 import kotlin.math.abs
 import kotlin.math.round
+import kotlin.math.roundToInt
 
 private inline class ScrollDirection(val isForward: Boolean)
 
@@ -358,7 +358,7 @@
             return measureScope.layout(width = width.ipx, height = height.ipx) {
                 var currentY = round(-firstItemScrollOffset)
                 rootNode.children.forEach {
-                    it.place(x = IntPx.Zero, y = currentY.px.round())
+                    it.place(x = IntPx.Zero, y = currentY.roundToInt().ipx)
                     currentY += it.height.value
                 }
             }
@@ -382,6 +382,10 @@
         }
     }
 
+    fun disposeAllChildren() {
+        removeAndDisposeChildren(LayoutIndex(0), rootNode.children.size)
+    }
+
     fun recomposeIfAttached() {
         if (rootNode.owner != null) {
             // TODO: run this in an `onPreCommit` callback for multithreaded/deferred composition
@@ -542,4 +546,7 @@
         measureBlocks = state.measureBlocks
     )
     state.recomposeIfAttached()
+    onDispose {
+        state.disposeAllChildren()
+    }
 }
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
index 65d54c7..f519eca 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
@@ -38,7 +38,7 @@
 import androidx.ui.semantics.enabled
 import androidx.ui.semantics.onClick
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastAny
 
 /**
@@ -181,7 +181,7 @@
  */
 @Composable
 private fun Modifier.noConsumptionIndicatorGestureFilter(
-    onStart: (PxPosition) -> Unit,
+    onStart: (Offset) -> Unit,
     onStop: () -> Unit,
     onCancel: () -> Unit
 ): Modifier = this + remember { NoConsumptionIndicatorGestureFilter(onStart, onStop, onCancel) }
@@ -190,7 +190,7 @@
  * Temporary, see [noConsumptionIndicatorGestureFilter]
  */
 private class NoConsumptionIndicatorGestureFilter(
-    val onStart: (PxPosition) -> Unit,
+    val onStart: (Offset) -> Unit,
     val onStop: () -> Unit,
     // Rename to avoid clashing with onCancel() function
     val onCancelCallback: () -> Unit
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
index 7daff24..8c41267 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
@@ -23,6 +23,7 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.composed
 import androidx.ui.geometry.Offset
+import androidx.ui.geometry.Radius
 import androidx.ui.geometry.Rect
 import androidx.ui.geometry.Size
 import androidx.ui.geometry.isSimple
@@ -205,8 +206,7 @@
             brush,
             topLeft = Offset(rect.left + delta, rect.top + delta),
             size = Size(rect.width - 2 * delta, rect.height - 2 * delta),
-            radiusX = radius,
-            radiusY = radius,
+            radius = Radius(radius),
             style = style
         )
     }
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/InteractionState.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/InteractionState.kt
index d10f73a..9b080fa 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/InteractionState.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/InteractionState.kt
@@ -21,7 +21,7 @@
 import androidx.compose.getValue
 import androidx.compose.mutableStateOf
 import androidx.compose.setValue
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * InteractionState represents a [Set] of [Interaction]s present on a given component. This
@@ -40,7 +40,7 @@
 @Stable
 class InteractionState : State<Set<Interaction>> {
 
-    private var map: Map<Interaction, PxPosition?> by mutableStateOf(emptyMap())
+    private var map: Map<Interaction, Offset?> by mutableStateOf(emptyMap())
 
     override val value: Set<Interaction>
         get() = map.keys
@@ -55,7 +55,7 @@
      * [Interaction.Pressed], this will be the position of the pointer input that triggered the
      * pressed state.
      */
-    fun addInteraction(interaction: Interaction, position: PxPosition? = null) {
+    fun addInteraction(interaction: Interaction, position: Offset? = null) {
         if (interaction !in this) map = map + (interaction to position)
     }
 
@@ -73,7 +73,7 @@
      * @return position associated with the interaction, or `null` if the interaction is not
      * present in this state, or there is no associated position with the given interaction.
      */
-    fun interactionPositionFor(interaction: Interaction): PxPosition? = map[interaction]
+    fun interactionPositionFor(interaction: Interaction): Offset? = map[interaction]
 
     /**
      * @return whether the provided [interaction] exists inside this InteractionState.
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
index 8ef06e3..6ce1365 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
@@ -47,7 +47,6 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.ipx
 import androidx.ui.unit.min
-import androidx.ui.unit.toPx
 import kotlin.math.roundToInt
 
 /**
@@ -325,14 +324,14 @@
             val placeable = measurables.first().measure(childConstraints)
             val width = min(placeable.width, constraints.maxWidth)
             val height = min(placeable.height, constraints.maxHeight)
-            val scrollHeight = placeable.height.toPx() - height.toPx()
-            val scrollWidth = placeable.width.toPx() - width.toPx()
+            val scrollHeight = placeable.height.value.toFloat() - height.value.toFloat()
+            val scrollWidth = placeable.width.value.toFloat() - width.value.toFloat()
             val side = if (isVertical) scrollHeight else scrollWidth
             layout(width, height) {
-                scrollerPosition.updateMaxPosition(side.value)
-                val scroll = scrollerPosition.value.coerceIn(0f, side.value)
+                scrollerPosition.updateMaxPosition(side)
+                val scroll = scrollerPosition.value.coerceIn(0f, side)
                 val absScroll =
-                    if (scrollerPosition.isReversed) scroll - side.value else -scroll
+                    if (scrollerPosition.isReversed) scroll - side else -scroll
                 val xOffset = if (isVertical) 0 else absScroll.roundToInt()
                 val yOffset = if (isVertical) absScroll.roundToInt() else 0
                 placeable.place(xOffset.ipx, yOffset.ipx)
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/DragDirection.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/DragDirection.kt
index fe7d19a..4c6c5f0 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/DragDirection.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/DragDirection.kt
@@ -17,7 +17,7 @@
 package androidx.ui.foundation.gestures
 
 import androidx.ui.core.Direction
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Draggable Direction specifies the direction in which you can drag an [draggable] or [scrollable].
@@ -33,7 +33,7 @@
         currentValue: Float
     ) -> Boolean
 
-    internal open fun project(pos: PxPosition) = xProjection(pos.x) + yProjection(pos.y)
+    internal open fun project(pos: Offset) = xProjection(pos.x) + yProjection(pos.y)
 
     /**
      * Horizontal direction of dragging in [draggable] or [scrollable].
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Draggable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Draggable.kt
index d929b46..efd8772 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Draggable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Draggable.kt
@@ -25,7 +25,7 @@
 import androidx.ui.core.gesture.dragGestureFilter
 import androidx.ui.foundation.Interaction
 import androidx.ui.foundation.InteractionState
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Configure touch dragging for the UI element in a single [DragDirection]. The drag distance is
@@ -60,7 +60,7 @@
  */
 fun Modifier.draggable(
     dragDirection: DragDirection,
-    onDragStarted: (startedPosition: PxPosition) -> Unit = {},
+    onDragStarted: (startedPosition: Offset) -> Unit = {},
     onDragStopped: (velocity: Float) -> Unit = {},
     enabled: Boolean = true,
     interactionState: InteractionState? = null,
@@ -74,20 +74,20 @@
     dragGestureFilter(
         dragObserver = object : DragObserver {
 
-            override fun onStart(downPosition: PxPosition) {
+            override fun onStart(downPosition: Offset) {
                 if (enabled) {
                     interactionState?.addInteraction(Interaction.Dragged)
                     onDragStarted(downPosition)
                 }
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 if (!enabled) return dragDistance
                 val projected = dragDirection.project(dragDistance)
                 val consumed = onDragDeltaConsumptionRequested(projected)
                 dragState.value = dragState.value + consumed
                 val fractionConsumed = if (projected == 0f) 0f else consumed / projected
-                return PxPosition(
+                return Offset(
                     dragDirection.xProjection(dragDistance.x) * fractionConsumed,
                     dragDirection.yProjection(dragDistance.y) * fractionConsumed
                 )
@@ -100,7 +100,7 @@
                 }
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 if (enabled) {
                     interactionState?.removeInteraction(Interaction.Dragged)
                     onDragStopped(dragDirection.project(velocity))
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Scrollable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Scrollable.kt
index d9c9ce6..c6aa03c 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Scrollable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Scrollable.kt
@@ -33,7 +33,7 @@
 import androidx.ui.core.gesture.dragGestureFilter
 import androidx.ui.foundation.animation.FlingConfig
 import androidx.ui.foundation.animation.fling
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Create [ScrollableState] for [scrollable] with default [FlingConfig] and
@@ -160,7 +160,7 @@
 fun Modifier.scrollable(
     dragDirection: DragDirection,
     scrollableState: ScrollableState,
-    onScrollStarted: (startedPosition: PxPosition) -> Unit = {},
+    onScrollStarted: (startedPosition: Offset) -> Unit = {},
     onScrollStopped: (velocity: Float) -> Unit = {},
     enabled: Boolean = true
 ): Modifier = composed {
@@ -170,20 +170,20 @@
     dragGestureFilter(
         dragObserver = object : DragObserver {
 
-            override fun onStart(downPosition: PxPosition) {
+            override fun onStart(downPosition: Offset) {
                 if (enabled) {
                     scrollableState.stopAnimation()
                     onScrollStarted(downPosition)
                 }
             }
 
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
-                if (!enabled) return PxPosition.Origin
+            override fun onDrag(dragDistance: Offset): Offset {
+                if (!enabled) return Offset.Zero
                 val projected = dragDirection.project(dragDistance)
                 val consumed = scrollableState.onScrollDeltaConsumptionRequested(projected)
                 scrollableState.value = scrollableState.value + consumed
                 val fractionConsumed = if (projected == 0f) 0f else consumed / projected
-                return PxPosition(
+                return Offset(
                     dragDirection.xProjection(dragDistance.x) * fractionConsumed,
                     dragDirection.yProjection(dragDistance.y) * fractionConsumed
                 )
@@ -194,7 +194,7 @@
                 if (enabled) onScrollStopped(0f)
             }
 
-            override fun onStop(velocity: PxPosition) {
+            override fun onStop(velocity: Offset) {
                 if (enabled) {
                     scrollableState.fling(dragDirection.project(velocity), onScrollStopped)
                 }
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Zoomable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Zoomable.kt
new file mode 100644
index 0000000..81c5875
--- /dev/null
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/gestures/Zoomable.kt
@@ -0,0 +1,139 @@
+/*
+ * 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.foundation.gestures
+
+import androidx.animation.AnimatedFloat
+import androidx.animation.AnimationClockObservable
+import androidx.animation.AnimationEndReason
+import androidx.animation.PhysicsBuilder
+import androidx.animation.Spring
+import androidx.compose.Composable
+import androidx.compose.remember
+import androidx.ui.animation.asDisposableClock
+import androidx.ui.core.AnimationClockAmbient
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScaleObserver
+import androidx.ui.core.gesture.scaleGestureFilter
+
+/**
+ * Create [ZoomableState] with default [AnimationClockObservable].
+ *
+ * @param onZoomDelta callback to be invoked when pinch/smooth zooming occurs. The callback
+ * receives the delta as the ratio of the new size compared to the old. Callers should update
+ * their state and UI in this callback.
+ */
+@Composable
+fun ZoomableState(onZoomDelta: (Float) -> Unit): ZoomableState {
+    val clocks = AnimationClockAmbient.current.asDisposableClock()
+    return remember(clocks) { ZoomableState(onZoomDelta, clocks) }
+}
+
+/**
+ * State of the [zoomable] composable modifier. Provides smooth scaling capabilities.
+ *
+ * @param onZoomDelta callback to be invoked when pinch/smooth zooming occurs. The callback
+ * receives the delta as the ratio of the new size compared to the old. Callers should update
+ * their state and UI in this callback.
+ * @param animationClock clock observable to run animation on. Consider querying
+ * [AnimationClockAmbient] to get current composition value
+ */
+class ZoomableState(val onZoomDelta: (Float) -> Unit, animationClock: AnimationClockObservable) {
+
+    /**
+     * Smooth scale by a ratio of [value] over the current size.
+     *
+     * @param value ratio over the current size by which to scale
+     * @pram [onEnd] callback invoked when the smooth scaling has ended
+     */
+    fun smoothScaleBy(
+        value: Float,
+        onEnd: ((endReason: AnimationEndReason, finishValue: Float) -> Unit)? = null
+    ) {
+        val to = animatedFloat.value * value
+        animatedFloat.animateTo(
+            to,
+            onEnd = onEnd,
+            anim = PhysicsBuilder(stiffness = Spring.StiffnessLow)
+        )
+    }
+
+    internal fun onScale(scaleFactor: Float) = onZoomDelta(scaleFactor)
+
+    private val animatedFloat = DeltaAnimatedScale(1f, animationClock, ::onScale)
+}
+
+/**
+ * Enable zooming of the modified UI element.
+ *
+ * [ZoomableState.onZoomDelta] will be invoked with the change in proportion of the UI element's
+ * size at each change in either ratio of the gesture or smooth scaling. Callers should update
+ * their state and UI in this callback.
+ *
+ * @sample androidx.ui.foundation.samples.ZoomableSample
+ *
+ * @param zoomableState [ZoomableState] object that holds the internal state of this zoomable,
+ * and provides smooth scaling capabilities.
+ * @param onZoomStopped callback to be invoked when zoom has stopped.
+ */
+@Composable
+fun Modifier.zoomable(zoomableState: ZoomableState, onZoomStopped: (() -> Unit)? = null): Modifier {
+    return scaleGestureFilter(
+            scaleObserver = object : ScaleObserver {
+                override fun onScale(scaleFactor: Float) = zoomableState.onScale(scaleFactor)
+
+                override fun onStop() {
+                    onZoomStopped?.invoke()
+                }
+            }
+        )
+}
+
+/**
+ * Enable zooming of the modified UI element.
+ *
+ * [onZoomDelta] will be invoked with the change in proportion of the UI element's
+ * size at each change in either position of the gesture or smooth scaling. Callers should update
+ * their state and UI in this callback.
+ *
+ * @sample androidx.ui.foundation.samples.ZoomableSample
+ *
+ * @param onZoomStopped callback to be invoked when zoom has stopped.
+ * @param onZoomDelta callback to be invoked when pinch/smooth zooming occurs. The callback
+ * receives the delta as the ratio of the new size compared to the old. Callers should update
+ * their state and UI in this callback.
+ */
+@Composable
+fun Modifier.zoomable(
+    onZoomStopped: (() -> Unit)? = null,
+    onZoomDelta: (Float) -> Unit
+) = Modifier.zoomable(ZoomableState(onZoomDelta), onZoomStopped)
+
+private class DeltaAnimatedScale(
+    initial: Float,
+    clock: AnimationClockObservable,
+    private val onDelta: (Float) -> Unit
+) : AnimatedFloat(clock) {
+
+    override var value = initial
+        set(value) {
+            if (isRunning) {
+                val delta = value / field
+                onDelta(delta)
+            }
+            field = value
+        }
+}
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/shape/corner/RoundedCornerShape.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/shape/corner/RoundedCornerShape.kt
index 54e04ee..ed8b813 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/shape/corner/RoundedCornerShape.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/shape/corner/RoundedCornerShape.kt
@@ -78,7 +78,7 @@
                 "$bottomRight, bottomLeft = $bottomLeft)"
     }
 
-    private /*inline*/ fun Float.toRadius() = Radius.circular(this)
+    private /*inline*/ fun Float.toRadius() = Radius(this)
 }
 
 /**
diff --git a/ui/ui-geometry/api/0.1.0-dev14.txt b/ui/ui-geometry/api/0.1.0-dev14.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/0.1.0-dev14.txt
+++ b/ui/ui-geometry/api/0.1.0-dev14.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/api/current.txt b/ui/ui-geometry/api/current.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/current.txt
+++ b/ui/ui-geometry/api/current.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev14.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev14.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/api/public_plus_experimental_current.txt b/ui/ui-geometry/api/public_plus_experimental_current.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/public_plus_experimental_current.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_current.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/api/restricted_0.1.0-dev14.txt b/ui/ui-geometry/api/restricted_0.1.0-dev14.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-geometry/api/restricted_0.1.0-dev14.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/api/restricted_current.txt b/ui/ui-geometry/api/restricted_current.txt
index 0ca2e11..ae4f76f 100644
--- a/ui/ui-geometry/api/restricted_current.txt
+++ b/ui/ui-geometry/api/restricted_current.txt
@@ -1,38 +1,30 @@
 // Signature format: 3.0
 package androidx.ui.geometry {
 
-  @androidx.compose.Immutable public final inline class Offset {
-    ctor public Offset();
-    method public static infix androidx.ui.geometry.Rect and-b2zCL34(long $this, long other);
-    method public static long constructor-impl(internal long packedValue);
-    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
-    method public static boolean equals-impl0(long p1, long p2);
-    method public static float getDirection-impl(long $this);
-    method @androidx.compose.Stable public static float getDistance-impl(long $this);
-    method @androidx.compose.Stable public static float getDistanceSquared-impl(long $this);
-    method public static float getDx-impl(long $this);
-    method public static float getDy-impl(long $this);
-    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
-    method @androidx.compose.Stable public static long scale-impl(long $this, float scaleX, float scaleY);
-    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
-    method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long translate-impl(long $this, float translateX, float translateY);
-    method public static long truncDiv-impl(long $this, float operand);
-    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
+  @androidx.compose.Immutable public final class Offset {
+    ctor public Offset(internal long packedValue);
+    method @androidx.compose.Immutable public androidx.ui.geometry.Offset copy(long packedValue);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset div(float operand);
+    method @androidx.compose.Stable public float getDistance();
+    method @androidx.compose.Stable public float getDistanceSquared();
+    method public float getX();
+    method public float getY();
+    method @androidx.compose.Stable public boolean isValid();
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset rem(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset times(float operand);
+    method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
+    property public final float x;
+    property public final float y;
     field public static final androidx.ui.geometry.Offset.Companion! Companion;
   }
 
   public static final class Offset.Companion {
-    method public long getInfinite();
-    method public long getZero();
-    method @androidx.compose.Stable public boolean isValid-RIqb49o(long offset);
-    method @androidx.compose.Stable public long lerp-nqy8KaQ(long start, long stop, float fraction);
-    property public final long infinite;
-    property public final long zero;
+    method public androidx.ui.geometry.Offset getInfinite();
+    method public androidx.ui.geometry.Offset getZero();
+    property public final androidx.ui.geometry.Offset Infinite;
+    property public final androidx.ui.geometry.Offset Zero;
   }
 
   public interface OffsetBase {
@@ -49,7 +41,8 @@
   }
 
   public final class OffsetKt {
-    method public static long Offset(float dx, float dy);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset(float x, float y);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset lerp(androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset stop, float fraction);
   }
 
   public final class RRect {
@@ -66,7 +59,7 @@
     method public float component7();
     method public float component8();
     method public float component9();
-    method public boolean contains-RIqb49o(long point);
+    method public boolean contains(androidx.ui.geometry.Offset point);
     method public androidx.ui.geometry.RRect copy(float left, float top, float right, float bottom, float topLeftRadiusX, float topLeftRadiusY, float topRightRadiusX, float topRightRadiusY, float bottomRightRadiusX, float bottomRightRadiusY, float bottomLeftRadiusX, float bottomLeftRadiusY);
     method @Deprecated public androidx.ui.geometry.RRect deflate(float delta);
     method public float getBottom();
@@ -97,14 +90,14 @@
 
   public final class RRectKt {
     method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius radius);
     method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, float radiusX, float radiusY);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius radius);
-    method public static androidx.ui.geometry.RRect RRect(float left, float top, float right, float bottom, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.RRect RRect(androidx.ui.geometry.Rect rect, androidx.ui.geometry.Radius topLeft = Radius.zero, androidx.ui.geometry.Radius topRight = Radius.zero, androidx.ui.geometry.Radius bottomRight = Radius.zero, androidx.ui.geometry.Radius bottomLeft = Radius.zero);
-    method public static androidx.ui.geometry.Radius bottomLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius bottomRightRadius(androidx.ui.geometry.RRect);
-    method public static long center(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.RRect RRect-SonKKtE(androidx.ui.geometry.Rect rect, long radius);
+    method public static androidx.ui.geometry.RRect RRect-a8KmX9Q(androidx.ui.geometry.Rect rect, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static androidx.ui.geometry.RRect RRect-iLOfVQs(float left, float top, float right, float bottom, long radius);
+    method public static androidx.ui.geometry.RRect RRect-kGjprzs(float left, float top, float right, float bottom, long topLeft = Radius.Zero, long topRight = Radius.Zero, long bottomRight = Radius.Zero, long bottomLeft = Radius.Zero);
+    method public static long bottomLeftRadius(androidx.ui.geometry.RRect);
+    method public static long bottomRightRadius(androidx.ui.geometry.RRect);
+    method public static androidx.ui.geometry.Offset center(androidx.ui.geometry.RRect);
     method public static float getLongestSide(androidx.ui.geometry.RRect);
     method public static float getShortestSide(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.RRect grow(androidx.ui.geometry.RRect, float delta);
@@ -119,41 +112,42 @@
     method public static androidx.ui.geometry.Rect middleRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect outerRect(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect safeInnerRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect shift-q6ZkaaM(androidx.ui.geometry.RRect, long offset);
+    method public static androidx.ui.geometry.RRect shift(androidx.ui.geometry.RRect, androidx.ui.geometry.Offset offset);
     method public static androidx.ui.geometry.RRect shrink(androidx.ui.geometry.RRect, float delta);
     method public static androidx.ui.geometry.Rect tallMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topLeftRadius(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.Radius topRightRadius(androidx.ui.geometry.RRect);
+    method public static long topLeftRadius(androidx.ui.geometry.RRect);
+    method public static long topRightRadius(androidx.ui.geometry.RRect);
     method public static androidx.ui.geometry.Rect wideMiddleRect(androidx.ui.geometry.RRect);
-    method public static androidx.ui.geometry.RRect withRadius(androidx.ui.geometry.RRect, androidx.ui.geometry.Radius radius);
+    method public static androidx.ui.geometry.RRect withRadius-ql9n_fM(androidx.ui.geometry.RRect, long radius);
   }
 
-  @androidx.compose.Immutable public final class Radius {
-    ctor public Radius(float x, float y);
-    method public float component1();
-    method public float component2();
-    method @androidx.compose.Immutable public androidx.ui.geometry.Radius copy(float x, float y);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius div(float operand);
-    method public float getX();
-    method public float getY();
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius minus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius plus(androidx.ui.geometry.Radius other);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius rem(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius times(float operand);
-    method public androidx.ui.geometry.Radius truncDiv(float operand);
-    method @androidx.compose.Stable public operator androidx.ui.geometry.Radius unaryMinus();
+  @androidx.compose.Immutable public final inline class Radius {
+    ctor public Radius();
+    method public static long constructor-impl(internal long packedValue);
+    method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
+    method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
+    method public static boolean equals-impl0(long p1, long p2);
+    method public static float getX-impl(long $this);
+    method public static float getY-impl(long $this);
+    method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
+    method @androidx.compose.Stable public static operator long minus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long plus-ASmZJvU(long $this, long other);
+    method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
+    method public static String toString-impl(long $this);
+    method public static long truncDiv-impl(long $this, float operand);
+    method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
     field public static final androidx.ui.geometry.Radius.Companion! Companion;
   }
 
   public static final class Radius.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius circular(float radius);
-    method @androidx.compose.Stable public androidx.ui.geometry.Radius elliptical(float x, float y);
-    method public androidx.ui.geometry.Radius getZero();
-    property public final androidx.ui.geometry.Radius zero;
+    method public long getZero();
+    property public final long Zero;
   }
 
   public final class RadiusKt {
-    method @androidx.compose.Stable public static androidx.ui.geometry.Radius lerp(androidx.ui.geometry.Radius start, androidx.ui.geometry.Radius stop, float fraction);
+    method @androidx.compose.Stable public static inline long Radius(float x, float y = x);
+    method @androidx.compose.Stable public static long lerp-LIZBhPY(long start, long stop, float fraction);
   }
 
   @androidx.compose.Immutable public final class Rect {
@@ -162,17 +156,17 @@
     method public float component2();
     method public float component3();
     method public float component4();
-    method public boolean contains-RIqb49o(long offset);
+    method public boolean contains(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Immutable public androidx.ui.geometry.Rect copy(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect deflate(float delta);
     method public androidx.ui.geometry.Rect expandToInclude(androidx.ui.geometry.Rect other);
     method public float getBottom();
-    method public long getBottomCenter();
-    method public long getBottomLeft();
-    method public long getBottomRight();
-    method public long getCenter();
-    method public long getCenterLeft();
-    method public long getCenterRight();
+    method public androidx.ui.geometry.Offset getBottomCenter();
+    method public androidx.ui.geometry.Offset getBottomLeft();
+    method public androidx.ui.geometry.Offset getBottomRight();
+    method public androidx.ui.geometry.Offset getCenter();
+    method public androidx.ui.geometry.Offset getCenterLeft();
+    method public androidx.ui.geometry.Offset getCenterRight();
     method public float getHeight();
     method public float getLeft();
     method public float getMaxDimension();
@@ -180,9 +174,9 @@
     method public float getRight();
     method public long getSize();
     method public float getTop();
-    method public long getTopCenter();
-    method public long getTopLeft();
-    method public long getTopRight();
+    method public androidx.ui.geometry.Offset getTopCenter();
+    method public androidx.ui.geometry.Offset getTopLeft();
+    method public androidx.ui.geometry.Offset getTopRight();
     method public float getWidth();
     method @androidx.compose.Stable public androidx.ui.geometry.Rect inflate(float delta);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect intersect(androidx.ui.geometry.Rect other);
@@ -191,7 +185,7 @@
     method @androidx.compose.Stable public boolean isInfinite();
     method public androidx.ui.geometry.Rect join(androidx.ui.geometry.Rect other);
     method public boolean overlaps(androidx.ui.geometry.Rect other);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift-RIqb49o(long offset);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect shift(androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect translate(float translateX, float translateY);
     property public final float height;
     property public final float maxDimension;
@@ -201,10 +195,10 @@
   }
 
   public static final class Rect.Companion {
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle-hSKLB2U(long center, float radius);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromCircle(androidx.ui.geometry.Offset center, float radius);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTRB(float left, float top, float right, float bottom);
     method @androidx.compose.Stable public androidx.ui.geometry.Rect fromLTWH(float left, float top, float width, float height);
-    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints-cs1Rg_A(long a, long b);
+    method @androidx.compose.Stable public androidx.ui.geometry.Rect fromPoints(androidx.ui.geometry.Offset a, androidx.ui.geometry.Offset b);
     method public androidx.ui.geometry.Rect getLargest();
     method public androidx.ui.geometry.Rect getZero();
     method public float get_giantScalar();
@@ -219,14 +213,14 @@
 
   @androidx.compose.Immutable public final inline class Size {
     ctor public Size();
-    method @androidx.compose.Stable public static long bottomCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long bottomRight-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long center-RIqb49o(long $this, long origin = Offset.zero);
-    method @androidx.compose.Stable public static long centerLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long centerRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset bottomRight-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center-impl(long $this, androidx.ui.geometry.Offset origin = Offset.Zero);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset centerRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method public static long constructor-impl(internal long value);
-    method @androidx.compose.Stable public static boolean contains-RIqb49o(long $this, long offset);
+    method @androidx.compose.Stable public static boolean contains-impl(long $this, androidx.ui.geometry.Offset offset);
     method @androidx.compose.Stable public static operator long div-impl(long $this, float operand);
     method @androidx.compose.Immutable public static inline boolean equals-impl(long p, Object? p1);
     method public static boolean equals-impl0(long p1, long p2);
@@ -237,15 +231,15 @@
     method public static float getWidth-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Stable public static boolean isEmpty-impl(long $this);
-    method @androidx.compose.Stable public static operator long minus-RIqb49o(long $this, long other);
-    method @androidx.compose.Stable public static operator long minus-b2zCL34(long $this, long other);
-    method @androidx.compose.Stable public static operator long plus-RIqb49o(long $this, long other);
+    method @androidx.compose.Stable public static operator androidx.ui.geometry.Offset minus-b2zCL34(long $this, long other);
+    method @androidx.compose.Stable public static operator long minus-impl(long $this, androidx.ui.geometry.Offset other);
+    method @androidx.compose.Stable public static operator long plus-impl(long $this, androidx.ui.geometry.Offset other);
     method @androidx.compose.Stable public static operator long rem-impl(long $this, float operand);
     method @androidx.compose.Stable public static operator long times-impl(long $this, float operand);
     method public static String toString-impl(long $this);
-    method @androidx.compose.Stable public static long topCenter-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topLeft-RIqb49o(long $this, long origin);
-    method @androidx.compose.Stable public static long topRight-RIqb49o(long $this, long origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topCenter-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topLeft-impl(long $this, androidx.ui.geometry.Offset origin);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset topRight-impl(long $this, androidx.ui.geometry.Offset origin);
     method @androidx.compose.Stable public static long truncDiv-impl(long $this, float operand);
     field public static final androidx.ui.geometry.Size.Companion! Companion;
   }
diff --git a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt
index af6c248..30fb6c0 100644
--- a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt
@@ -23,14 +23,14 @@
 import androidx.ui.util.toStringAsFixed
 import androidx.ui.util.unpackFloat1
 import androidx.ui.util.unpackFloat2
-import kotlin.math.atan2
 import kotlin.math.sqrt
-import kotlin.math.truncate
 
 /**
  * Constructs an Offset from the given relative x and y offsets
  */
-fun Offset(dx: Float, dy: Float) = Offset(packFloats(dx, dy))
+@Suppress("NOTHING_TO_INLINE")
+@Stable
+inline fun Offset(x: Float, y: Float) = Offset(packFloats(x, y))
 
 /**
  * An immutable 2D floating-point offset.
@@ -55,18 +55,20 @@
  *
  *  * [Size], which represents a vector describing the size of a rectangle.
  *
- * Creates an offset. The first argument sets [dx], the horizontal component,
- * and the second sets [dy], the vertical component.
+ * Creates an offset. The first argument sets [x], the horizontal component,
+ * and the second sets [y], the vertical component.
  */
+// TODO njawad make this an inline class again once the fix for b/155690960 has been picked
+//   up by the compose kotlin compiler
 @Immutable
-inline class Offset(@PublishedApi internal val packedValue: Long) {
+/* inline */ data class Offset(@PublishedApi internal val packedValue: Long) {
 
     @Stable
-    val dx: Float
+    val x: Float
         get() = unpackFloat1(packedValue)
 
     @Stable
-    val dy: Float
+    val y: Float
         get() = unpackFloat2(packedValue)
 
     companion object {
@@ -76,7 +78,7 @@
          * This can be used to represent the origin of a coordinate space.
          */
         @Stable
-        val zero = Offset(0.0f, 0.0f)
+        val Zero = Offset(0.0f, 0.0f)
 
         /**
          * An offset with infinite x and y components.
@@ -88,38 +90,15 @@
          */
         // This is included for completeness, because [Size.infinite] exists.
         @Stable
-        val infinite = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
+        val Infinite = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
+    }
 
-        /**
-         * Linearly interpolate between two offsets.
-         *
-         * The [fraction] argument represents position on the timeline, with 0.0 meaning
-         * that the interpolation has not started, returning [start] (or something
-         * equivalent to [start]), 1.0 meaning that the interpolation has finished,
-         * returning [stop] (or something equivalent to [stop]), and values in between
-         * meaning that the interpolation is at the relevant point on the timeline
-         * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
-         * 1.0, so negative values and values greater than 1.0 are valid (and can
-         * easily be generated by curves).
-         *
-         * Values for [fraction] are usually obtained from an [Animation<Float>], such as
-         * an `AnimationController`.
-         */
-        @Stable
-        fun lerp(start: Offset, stop: Offset, fraction: Float): Offset {
-            return Offset(
-                lerp(start.dx, stop.dx, fraction),
-                lerp(start.dy, stop.dy, fraction)
-            )
+    @Stable
+    fun isValid(): Boolean {
+        check(!x.isNaN() && !y.isNaN()) {
+            "Offset argument contained a NaN value."
         }
-
-        @Stable
-        fun isValid(offset: Offset): Boolean {
-            check(!offset.dx.isNaN() && !offset.dy.isNaN()) {
-                "Offset argument contained a NaN value."
-            }
-            return true
-        }
+        return true
     }
 
     /**
@@ -129,7 +108,7 @@
      * consider using [getDistanceSquared] instead, since it is cheaper to compute.
      */
     @Stable
-    fun getDistance() = sqrt(dx * dx + dy * dy)
+    fun getDistance() = sqrt(x * x + y * y)
 
     /**
      * The square of the magnitude of the offset.
@@ -137,79 +116,7 @@
      * This is cheaper than computing the [getDistance] itself.
      */
     @Stable
-    fun getDistanceSquared() = dx * dx + dy * dy
-
-    /**
-     * The angle of this offset as radians clockwise from the positive x-axis, in
-     * the range -[pi] to [pi], assuming positive values of the x-axis go to the
-     * left and positive values of the y-axis go down.
-     *
-     * Zero means that [dy] is zero and [dx] is zero or positive.
-     *
-     * Values from zero to [pi]/2 indicate positive values of [dx] and [dy], the
-     * bottom-right quadrant.
-     *
-     * Values from [pi]/2 to [pi] indicate negative values of [dx] and positive
-     * values of [dy], the bottom-left quadrant.
-     *
-     * Values from zero to -[pi]/2 indicate positive values of [dx] and negative
-     * values of [dy], the top-right quadrant.
-     *
-     * Values from -[pi]/2 to -[pi] indicate negative values of [dx] and [dy],
-     * the top-left quadrant.
-     *
-     * When [dy] is zero and [dx] is negative, the [direction] is [pi].
-     *
-     * When [dx] is zero, [direction] is [pi]/2 if [dy] is positive and -[pi]/2
-     * if [dy] is negative.
-     *
-     * See also:
-     *
-     *  * [distance], to compute the magnitude of the vector.
-     *  * [Canvas.rotate], which uses the same convention for its angle.
-     */
-    fun getDirection() = atan2(dy, dx)
-
-    /**
-     * Returns a new offset with the x component scaled by `scaleX` and the y
-     * component scaled by `scaleY`.
-     *
-     * If the two scale arguments are the same, consider using the `*` operator
-     * instead:
-     *
-     * ```dart
-     * Offset a = const Offset(10.0, 10.0);
-     * Offset b = a * 2.0; // same as: a.scale(2.0, 2.0)
-     * ```
-     *
-     * If the two arguments are -1, consider using the unary `-` operator
-     * instead:
-     *
-     * ```dart
-     * Offset a = const Offset(10.0, 10.0);
-     * Offset b = -a; // same as: a.scale(-1.0, -1.0)
-     * ```
-     */
-    @Stable
-    fun scale(scaleX: Float, scaleY: Float): Offset = Offset(dx * scaleX, dy * scaleY)
-
-    /**
-     * Returns a new offset with translateX added to the x component and
-     * translateY added to the y component.
-     *
-     * If the arguments come from another [Offset], consider using the `+` or `-`
-     * operators instead:
-     *
-     * ```dart
-     * Offset a = const Offset(10.0, 10.0);
-     * Offset b = const Offset(10.0, 10.0);
-     * Offset c = a + b; // same as: a.translate(b.dx, b.dy)
-     * Offset d = a - b; // same as: a.translate(-b.dx, -b.dy)
-     * ```
-     */
-    @Stable
-    fun translate(translateX: Float, translateY: Float): Offset =
-        Offset(dx + translateX, dy + translateY)
+    fun getDistanceSquared() = x * x + y * y
 
     /**
      * Unary negation operator.
@@ -220,31 +127,27 @@
      * same arrow but pointing in the reverse direction.
      */
     @Stable
-    operator fun unaryMinus(): Offset = Offset(-dx, -dy)
+    operator fun unaryMinus(): Offset = Offset(-x, -y)
 
     /**
      * Binary subtraction operator.
      *
-     * Returns an offset whose [dx] value is the left-hand-side operand's [dx]
-     * minus the right-hand-side operand's [dx] and whose [dy] value is the
-     * left-hand-side operand's [dy] minus the right-hand-side operand's [dy].
-     *
-     * See also [translate].
+     * Returns an offset whose [x] value is the left-hand-side operand's [x]
+     * minus the right-hand-side operand's [x] and whose [y] value is the
+     * left-hand-side operand's [y] minus the right-hand-side operand's [y].
      */
     @Stable
-    operator fun minus(other: Offset): Offset = Offset(dx - other.dx, dy - other.dy)
+    operator fun minus(other: Offset): Offset = Offset(x - other.x, y - other.y)
 
     /**
      * Binary addition operator.
      *
-     * Returns an offset whose [dx] value is the sum of the [dx] values of the
-     * two operands, and whose [dy] value is the sum of the [dy] values of the
+     * Returns an offset whose [x] value is the sum of the [x] values of the
+     * two operands, and whose [y] value is the sum of the [y] values of the
      * two operands.
-     *
-     * See also [translate].
      */
     @Stable
-    operator fun plus(other: Offset): Offset = Offset(dx + other.dx, dy + other.dy)
+    operator fun plus(other: Offset): Offset = Offset(x + other.x, y + other.y)
 
     /**
      * Multiplication operator.
@@ -252,11 +155,9 @@
      * Returns an offset whose coordinates are the coordinates of the
      * left-hand-side operand (an Offset) multiplied by the scalar
      * right-hand-side operand (a Float).
-     *
-     * See also [scale].
      */
     @Stable
-    operator fun times(operand: Float): Offset = Offset(dx * operand, dy * operand)
+    operator fun times(operand: Float): Offset = Offset(x * operand, y * operand)
 
     /**
      * Division operator.
@@ -264,22 +165,9 @@
      * Returns an offset whose coordinates are the coordinates of the
      * left-hand-side operand (an Offset) divided by the scalar right-hand-side
      * operand (a Float).
-     *
-     * See also [scale].
      */
     @Stable
-    operator fun div(operand: Float): Offset = Offset(dx / operand, dy / operand)
-
-    /**
-     * Integer (truncating) division operator.
-     *
-     * Returns an offset whose coordinates are the coordinates of the
-     * left-hand-side operand (an Offset) divided by the scalar right-hand-side
-     * operand (a Float), rounded towards zero.
-     */
-    // TODO(Filip): Original operator ~/ could not be overriden in Kotlin
-    fun truncDiv(operand: Float) =
-        Offset(truncate(dx / operand), truncate(dy / operand))
+    operator fun div(operand: Float): Offset = Offset(x / operand, y / operand)
 
     /**
      * Modulo (remainder) operator.
@@ -289,22 +177,30 @@
      * right-hand-side operand (a Float).
      */
     @Stable
-    operator fun rem(operand: Float) = Offset(dx % operand, dy % operand)
+    operator fun rem(operand: Float) = Offset(x % operand, y % operand)
 
-    /**
-     * Rectangle constructor operator.
-     *
-     * Combines an [Offset] and a [Size] to form a [Rect] whose top-left
-     * coordinate is the point given by adding this offset, the left-hand-side
-     * operand, to the origin, and whose size is the right-hand-side operand.
-     *
-     * ```dart
-     * Rect myRect = Offset.zero & const Size(100.0, 100.0);
-     * // same as: new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0)
-     * ```
-     */
-    // TODO(Filip): Original operator & could not be overriden in Kotlin
-    infix fun and(other: Size): Rect = Rect.fromLTWH(dx, dy, other.width, other.height)
+    override fun toString() = "Offset(${x.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})"
+}
 
-    override fun toString() = "Offset(${dx.toStringAsFixed(1)}, ${dy.toStringAsFixed(1)})"
+/**
+ * Linearly interpolate between two offsets.
+ *
+ * The [fraction] argument represents position on the timeline, with 0.0 meaning
+ * that the interpolation has not started, returning [start] (or something
+ * equivalent to [start]), 1.0 meaning that the interpolation has finished,
+ * returning [stop] (or something equivalent to [stop]), and values in between
+ * meaning that the interpolation is at the relevant point on the timeline
+ * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
+ * 1.0, so negative values and values greater than 1.0 are valid (and can
+ * easily be generated by curves).
+ *
+ * Values for [fraction] are usually obtained from an [Animation<Float>], such as
+ * an `AnimationController`.
+ */
+@Stable
+fun lerp(start: Offset, stop: Offset, fraction: Float): Offset {
+    return Offset(
+        lerp(start.x, stop.x, fraction),
+        lerp(start.y, stop.y, fraction)
+    )
 }
\ No newline at end of file
diff --git a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
index e093dab..69a9925 100644
--- a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
@@ -119,7 +119,7 @@
      * recreating the object each time.
      */
     fun contains(point: Offset): Boolean {
-        if (point.dx < left || point.dx >= right || point.dy < top || point.dy >= bottom) {
+        if (point.x < left || point.x >= right || point.y < top || point.y >= bottom) {
             return false; // outside bounding box
         }
 
@@ -131,32 +131,32 @@
         val radiusY: Float
         // check whether point is in one of the rounded corner areas
         // x, y -> translate to ellipse center
-        if (point.dx < left + scaled.topLeftRadiusX &&
-            point.dy < top + scaled.topLeftRadiusY
+        if (point.x < left + scaled.topLeftRadiusX &&
+            point.y < top + scaled.topLeftRadiusY
         ) {
-            x = point.dx - left - scaled.topLeftRadiusX
-            y = point.dy - top - scaled.topLeftRadiusY
+            x = point.x - left - scaled.topLeftRadiusX
+            y = point.y - top - scaled.topLeftRadiusY
             radiusX = scaled.topLeftRadiusX
             radiusY = scaled.topLeftRadiusY
-        } else if (point.dx > right - scaled.topRightRadiusX &&
-            point.dy < top + scaled.topRightRadiusY
+        } else if (point.x > right - scaled.topRightRadiusX &&
+            point.y < top + scaled.topRightRadiusY
         ) {
-            x = point.dx - right + scaled.topRightRadiusX
-            y = point.dy - top - scaled.topRightRadiusY
+            x = point.x - right + scaled.topRightRadiusX
+            y = point.y - top - scaled.topRightRadiusY
             radiusX = scaled.topRightRadiusX
             radiusY = scaled.topRightRadiusY
-        } else if (point.dx > right - scaled.bottomRightRadiusX &&
-            point.dy > bottom - scaled.bottomRightRadiusY
+        } else if (point.x > right - scaled.bottomRightRadiusX &&
+            point.y > bottom - scaled.bottomRightRadiusY
         ) {
-            x = point.dx - right + scaled.bottomRightRadiusX
-            y = point.dy - bottom + scaled.bottomRightRadiusY
+            x = point.x - right + scaled.bottomRightRadiusX
+            y = point.y - bottom + scaled.bottomRightRadiusY
             radiusX = scaled.bottomRightRadiusX
             radiusY = scaled.bottomRightRadiusY
-        } else if (point.dx < left + scaled.bottomLeftRadiusX &&
-            point.dy > bottom - scaled.bottomLeftRadiusY
+        } else if (point.x < left + scaled.bottomLeftRadiusX &&
+            point.y > bottom - scaled.bottomLeftRadiusY
         ) {
-            x = point.dx - left - scaled.bottomLeftRadiusX
-            y = point.dy - bottom + scaled.bottomLeftRadiusY
+            x = point.x - left - scaled.bottomLeftRadiusX
+            y = point.y - bottom + scaled.bottomLeftRadiusY
             radiusX = scaled.bottomLeftRadiusX
             radiusY = scaled.bottomLeftRadiusY
         } else {
@@ -302,17 +302,17 @@
  * Construct a rounded rectangle from its left, top, right, and bottom edges,
  * and topLeft, topRight, bottomRight, and bottomLeft radii.
  *
- * The corner radii default to [Radius.zero], i.e. right-angled corners.
+ * The corner radii default to [Radius.Zero], i.e. right-angled corners.
  */
 fun RRect(
     left: Float,
     top: Float,
     right: Float,
     bottom: Float,
-    topLeft: Radius = Radius.zero,
-    topRight: Radius = Radius.zero,
-    bottomRight: Radius = Radius.zero,
-    bottomLeft: Radius = Radius.zero
+    topLeft: Radius = Radius.Zero,
+    topRight: Radius = Radius.Zero,
+    bottomRight: Radius = Radius.Zero,
+    bottomLeft: Radius = Radius.Zero
 ): RRect = RRect(
     left = left,
     top = top,
@@ -332,14 +332,14 @@
  * Construct a rounded rectangle from its bounding box and and topLeft,
  * topRight, bottomRight, and bottomLeft radii.
  *
- * The corner radii default to [Radius.zero], i.e. right-angled corners
+ * The corner radii default to [Radius.Zero], i.e. right-angled corners
  */
 fun RRect(
     rect: Rect,
-    topLeft: Radius = Radius.zero,
-    topRight: Radius = Radius.zero,
-    bottomRight: Radius = Radius.zero,
-    bottomLeft: Radius = Radius.zero
+    topLeft: Radius = Radius.Zero,
+    topRight: Radius = Radius.Zero,
+    bottomRight: Radius = Radius.Zero,
+    bottomLeft: Radius = Radius.Zero
 ): RRect = RRect(
     left = rect.left,
     top = rect.top,
@@ -356,27 +356,27 @@
 )
 
 /** The top-left [Radius]. */
-fun RRect.topLeftRadius(): Radius = Radius.elliptical(topLeftRadiusX, topLeftRadiusY)
+fun RRect.topLeftRadius(): Radius = Radius(topLeftRadiusX, topLeftRadiusY)
 
 /**  The top-right [Radius]. */
-fun RRect.topRightRadius(): Radius = Radius.elliptical(topRightRadiusX, topRightRadiusY)
+fun RRect.topRightRadius(): Radius = Radius(topRightRadiusX, topRightRadiusY)
 
 /**  The bottom-right [Radius]. */
-fun RRect.bottomRightRadius(): Radius = Radius.elliptical(bottomRightRadiusX, bottomRightRadiusY)
+fun RRect.bottomRightRadius(): Radius = Radius(bottomRightRadiusX, bottomRightRadiusY)
 
 /** The bottom-left [Radius]. */
-fun RRect.bottomLeftRadius(): Radius = Radius.elliptical(bottomLeftRadiusX, bottomLeftRadiusY)
+fun RRect.bottomLeftRadius(): Radius = Radius(bottomLeftRadiusX, bottomLeftRadiusY)
 
 /** Returns a new [RRect] translated by the given offset. */
 fun RRect.shift(offset: Offset): RRect = RRect(
-    left = left + offset.dx,
-    top = top + offset.dy,
-    right = right + offset.dx,
-    bottom = bottom + offset.dy,
-    topLeft = Radius.elliptical(topLeftRadiusX, topLeftRadiusY),
-    topRight = Radius.elliptical(topRightRadiusX, topRightRadiusY),
-    bottomRight = Radius.elliptical(bottomRightRadiusX, bottomRightRadiusY),
-    bottomLeft = Radius.elliptical(bottomLeftRadiusX, bottomLeftRadiusY)
+    left = left + offset.x,
+    top = top + offset.y,
+    right = right + offset.x,
+    bottom = bottom + offset.y,
+    topLeft = Radius(topLeftRadiusX, topLeftRadiusY),
+    topRight = Radius(topRightRadiusX, topRightRadiusY),
+    bottomRight = Radius(bottomRightRadiusX, bottomRightRadiusY),
+    bottomLeft = Radius(bottomLeftRadiusX, bottomLeftRadiusY)
 )
 
 /**
@@ -388,10 +388,10 @@
     top = top - delta,
     right = right + delta,
     bottom = bottom + delta,
-    topLeft = Radius.elliptical(topLeftRadiusX + delta, topLeftRadiusY + delta),
-    topRight = Radius.elliptical(topRightRadiusX + delta, topRightRadiusY + delta),
-    bottomRight = Radius.elliptical(bottomRightRadiusX + delta, bottomRightRadiusY + delta),
-    bottomLeft = Radius.elliptical(bottomLeftRadiusX + delta, bottomLeftRadiusY + delta)
+    topLeft = Radius(topLeftRadiusX + delta, topLeftRadiusY + delta),
+    topRight = Radius(topRightRadiusX + delta, topRightRadiusY + delta),
+    bottomRight = Radius(bottomRightRadiusX + delta, bottomRightRadiusY + delta),
+    bottomLeft = Radius(bottomLeftRadiusX + delta, bottomLeftRadiusY + delta)
 )
 
 fun RRect.withRadius(radius: Radius): RRect = RRect(
diff --git a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt
index 2648f74..38b1e3d 100644
--- a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt
@@ -19,40 +19,44 @@
 import androidx.compose.Immutable
 import androidx.compose.Stable
 import androidx.ui.util.lerp
+import androidx.ui.util.packFloats
 import androidx.ui.util.toStringAsFixed
+import androidx.ui.util.unpackFloat1
+import androidx.ui.util.unpackFloat2
 import kotlin.math.truncate
 
+/**
+ * Constructs a Radius with the given [x] and [y] parameters for the
+ * size of the radius along the x and y axis respectively. By default
+ * the radius along the Y axis matches that of the given x-axis
+ * unless otherwise specified
+ */
+@Suppress("NOTHING_TO_INLINE")
+@Stable
+inline fun Radius(x: Float, y: Float = x) = Radius(packFloats(x, y))
+
 /** A radius for either circular or elliptical shapes. */
 @Immutable
-data class Radius(
+inline class Radius(@PublishedApi internal val packedValue: Long) {
+
     /** The radius value on the horizontal axis. */
     @Stable
-    val x: Float,
+    val x: Float
+        get() = unpackFloat1(packedValue)
     /** The radius value on the vertical axis. */
     @Stable
     val y: Float
-) {
+        get() = unpackFloat2(packedValue)
 
     companion object {
-        /** Constructs a circular radius. [x] and [y] will have the same radius value. */
-        @Stable
-        fun circular(radius: Float): Radius {
-            return Radius(radius, radius)
-        }
-
-        /** Constructs an elliptical radius with the given radii. */
-        @Stable
-        fun elliptical(x: Float, y: Float): Radius {
-            return Radius(x, y)
-        }
 
         /**
          * A radius with [x] and [y] values set to zero.
          *
-         * You can use [Radius.zero] with [RRect] to have right-angle corners.
+         * You can use [Radius.Zero] with [RRect] to have right-angle corners.
          */
         @Stable
-        val zero: Radius = circular(0.0f)
+        val Zero: Radius = Radius(0.0f)
     }
 
     /**
@@ -66,7 +70,7 @@
      * a radius of one pixel from the other.
      */
     @Stable
-    operator fun unaryMinus() = elliptical(-x, -y)
+    operator fun unaryMinus() = Radius(-x, -y)
 
     /**
      * Binary subtraction operator.
@@ -76,7 +80,7 @@
      * left-hand-side operand's [y] minus the right-hand-side operand's [y].
      */
     @Stable
-    operator fun minus(other: Radius) = elliptical(x - other.x, y - other.y)
+    operator fun minus(other: Radius) = Radius(x - other.x, y - other.y)
 
     /**
      * Binary addition operator.
@@ -86,7 +90,7 @@
      * two operands.
      */
     @Stable
-    operator fun plus(other: Radius) = elliptical(x + other.x, y + other.y)
+    operator fun plus(other: Radius) = Radius(x + other.x, y + other.y)
 
     /**
      * Multiplication operator.
@@ -96,7 +100,7 @@
      * right-hand-side operand (a Float).
      */
     @Stable
-    operator fun times(operand: Float) = elliptical(x * operand, y * operand)
+    operator fun times(operand: Float) = Radius(x * operand, y * operand)
 
     /**
      * Division operator.
@@ -106,7 +110,7 @@
      * operand (a Float).
      */
     @Stable
-    operator fun div(operand: Float) = elliptical(x / operand, y / operand)
+    operator fun div(operand: Float) = Radius(x / operand, y / operand)
 
     /**
      * Integer (truncating) division operator.
@@ -116,7 +120,7 @@
      * operand (a Float), rounded towards zero.
      */
     fun truncDiv(operand: Float): Radius =
-        elliptical(truncate(x / operand), truncate(y / operand))
+        Radius(truncate(x / operand), truncate(y / operand))
 
     /**
      * Modulo (remainder) operator.
@@ -126,7 +130,7 @@
      * right-hand-side operand (a Float).
      */
     @Stable
-    operator fun rem(operand: Float) = elliptical(x % operand, y % operand)
+    operator fun rem(operand: Float) = Radius(x % operand, y % operand)
 
     override fun toString(): String {
         return if (x == y) {
@@ -135,20 +139,6 @@
             "Radius.elliptical(${x.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})"
         }
     }
-
-// TODO(Filip): I think data class handles this no need to re-implement
-//    @override
-//    bool operator ==(dynamic other) {
-//        if (identical(this, other))
-//            return true;
-//        if (runtimeType != other.runtimeType)
-//            return false;
-//        final Radius typedOther = other;
-//        return typedOther.x == x && typedOther.y == y;
-//    }
-//
-//    @override
-//    int get hashCode => hashValues(x, y);
 }
 
 /**
@@ -168,7 +158,7 @@
  */
 @Stable
 fun lerp(start: Radius, stop: Radius, fraction: Float): Radius {
-    return Radius.elliptical(
+    return Radius(
         lerp(start.x, stop.x, fraction),
         lerp(start.y, stop.y, fraction)
     )
diff --git a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
index 9ebaf29..2fbe835 100644
--- a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
@@ -79,10 +79,10 @@
         @Stable
         fun fromCircle(center: Offset, radius: Float): Rect {
             return Rect(
-                center.dx - radius,
-                center.dy - radius,
-                center.dx + radius,
-                center.dy + radius
+                center.x - radius,
+                center.y - radius,
+                center.x + radius,
+                center.y + radius
             )
         }
 
@@ -93,10 +93,10 @@
         @Stable
         fun fromPoints(a: Offset, b: Offset): Rect {
             return Rect(
-                min(a.dx, b.dx),
-                min(a.dy, b.dy),
-                max(a.dx, b.dx),
-                max(a.dy, b.dy)
+                min(a.x, b.x),
+                min(a.y, b.y),
+                max(a.x, b.x),
+                max(a.y, b.y)
             )
         }
 
@@ -177,7 +177,7 @@
      */
     @Stable
     fun shift(offset: Offset): Rect {
-        return fromLTRB(left + offset.dx, top + offset.dy, right + offset.dx, bottom + offset.dy)
+        return fromLTRB(left + offset.x, top + offset.y, right + offset.x, bottom + offset.y)
     }
 
     /**
@@ -344,7 +344,7 @@
      * right edges.
      */
     fun contains(offset: Offset): Boolean {
-        return offset.dx >= left && offset.dx < right && offset.dy >= top && offset.dy < bottom
+        return offset.x >= left && offset.x < right && offset.y >= top && offset.y < bottom
     }
 
     override fun toString() = "Rect.fromLTRB(" +
diff --git a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt
index 10ca029..81306e7 100644
--- a/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt
@@ -161,14 +161,14 @@
      * Subtracting an [Offset] from a [Size] returns the [Size] that is smaller than
      * the [Size] operand by the difference given by the [Offset] operand. In other
      * words, the returned [Size] has a [width] consisting of the [width] of the
-     * left-hand-side operand minus the [Offset.dx] dimension of the
+     * left-hand-side operand minus the [Offset.x] dimension of the
      * right-hand-side operand, and a [height] consisting of the [height] of the
-     * left-hand-side operand minus the [Offset.dy] dimension of the
+     * left-hand-side operand minus the [Offset.y] dimension of the
      * right-hand-side operand.
      */
     @Stable
     operator fun minus(other: Offset): Size {
-        return Size(width - other.dx, height - other.dy)
+        return Size(width - other.x, height - other.y)
     }
 
     @Stable
@@ -180,13 +180,13 @@
      * Binary addition operator for adding an [Offset] to a [Size].
      *
      * Returns a [Size] whose [width] is the sum of the [width] of the
-     * left-hand-side operand, a [Size], and the [Offset.dx] dimension of the
+     * left-hand-side operand, a [Size], and the [Offset.x] dimension of the
      * right-hand-side operand, an [Offset], and whose [height] is the sum of the
-     * [height] of the left-hand-side operand and the [Offset.dy] dimension of
+     * [height] of the left-hand-side operand and the [Offset.y] dimension of
      * the right-hand-side operand.
      */
     @Stable
-    operator fun plus(other: Offset) = Size(width + other.dx, height + other.dy)
+    operator fun plus(other: Offset) = Size(width + other.x, height + other.y)
 
     /**
      * Multiplication operator.
@@ -263,7 +263,7 @@
      * See also [Rect.topCenter].
      */
     @Stable
-    fun topCenter(origin: Offset): Offset = Offset(origin.dx + width / 2.0f, origin.dy)
+    fun topCenter(origin: Offset): Offset = Offset(origin.x + width / 2.0f, origin.y)
 
     /**
      * The offset to the intersection of the top and right edges of the rectangle
@@ -273,7 +273,7 @@
      * See also [Rect.topRight].
      */
     @Stable
-    fun topRight(origin: Offset): Offset = Offset(origin.dx + width, origin.dy)
+    fun topRight(origin: Offset): Offset = Offset(origin.x + width, origin.y)
 
     /**
      * The offset to the center of the left edge of the rectangle described by the
@@ -282,7 +282,7 @@
      * See also [Rect.centerLeft].
      */
     @Stable
-    fun centerLeft(origin: Offset): Offset = Offset(origin.dx, origin.dy + height / 2.0f)
+    fun centerLeft(origin: Offset): Offset = Offset(origin.x, origin.y + height / 2.0f)
 
     /**
      * The offset to the point halfway between the left and right and the top and
@@ -292,7 +292,7 @@
      * See also [Rect.center].
      */
     @Stable
-    fun center(origin: Offset = Offset.zero): Offset = Offset(origin.dx + width / 2.0f, origin.dy +
+    fun center(origin: Offset = Offset.Zero): Offset = Offset(origin.x + width / 2.0f, origin.y +
             height / 2.0f)
 
     /**
@@ -302,7 +302,7 @@
      * See also [Rect.centerLeft].
      */
     @Stable
-    fun centerRight(origin: Offset): Offset = Offset(origin.dx + width, origin.dy + height / 2.0f)
+    fun centerRight(origin: Offset): Offset = Offset(origin.x + width, origin.y + height / 2.0f)
 
     /**
      * The offset to the intersection of the bottom and left edges of the
@@ -312,7 +312,7 @@
      * See also [Rect.bottomLeft].
      */
     @Stable
-    fun bottomLeft(origin: Offset): Offset = Offset(origin.dx, origin.dy + height)
+    fun bottomLeft(origin: Offset): Offset = Offset(origin.x, origin.y + height)
 
     /**
      * The offset to the center of the bottom edge of the rectangle described by
@@ -322,7 +322,7 @@
      * See also [Rect.bottomLeft].
      */
     @Stable
-    fun bottomCenter(origin: Offset): Offset = Offset(origin.dx + width / 2.0f, origin.dy + height)
+    fun bottomCenter(origin: Offset): Offset = Offset(origin.x + width / 2.0f, origin.y + height)
 
     /**
      * The offset to the intersection of the bottom and right edges of the
@@ -332,7 +332,7 @@
      * See also [Rect.bottomRight].
      */
     @Stable
-    fun bottomRight(origin: Offset): Offset = Offset(origin.dx + width, origin.dy + height)
+    fun bottomRight(origin: Offset): Offset = Offset(origin.x + width, origin.y + height)
 
     /**
      * Whether the point specified by the given offset (which is assumed to be
@@ -344,7 +344,7 @@
      */
     @Stable
     fun contains(offset: Offset): Boolean {
-        return offset.dx >= 0.0f && offset.dx < width && offset.dy >= 0.0f && offset.dy < height
+        return offset.x >= 0.0f && offset.x < width && offset.y >= 0.0f && offset.y < height
     }
 
     /**
diff --git a/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt b/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt
index ae93b58..5a63415 100644
--- a/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt
+++ b/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt
@@ -33,10 +33,10 @@
     fun `RRect_contains()`() {
         val rrect = RRect(
                 Rect.fromLTRB(1.0f, 1.0f, 2.0f, 2.0f),
-                topLeft = Radius.circular(0.5f),
-                topRight = Radius.circular(0.25f),
-                bottomRight = Radius.elliptical(0.25f, 0.75f),
-                bottomLeft = Radius.zero
+                topLeft = Radius(0.5f),
+                topRight = Radius(0.25f),
+                bottomRight = Radius(0.25f, 0.75f),
+                bottomLeft = Radius.Zero
         )
 
         assertFalse(rrect.contains(Offset(1.0f, 1.0f)))
@@ -53,10 +53,10 @@
     fun `RRect_contains() large radii`() {
         val rrect = RRect(
                 Rect.fromLTRB(1.0f, 1.0f, 2.0f, 2.0f),
-                topLeft = Radius.circular(5000.0f),
-                topRight = Radius.circular(2500.0f),
-                bottomRight = Radius.elliptical(2500.0f, 7500.0f),
-                bottomLeft = Radius.zero
+                topLeft = Radius(5000.0f),
+                topRight = Radius(2500.0f),
+                bottomRight = Radius(2500.0f, 7500.0f),
+                bottomLeft = Radius.Zero
         )
 
         assertFalse(rrect.contains(Offset(1.0f, 1.0f)))
diff --git a/ui/ui-graphics/api/0.1.0-dev14.txt b/ui/ui-graphics/api/0.1.0-dev14.txt
index db17451..1ded5ae 100644
--- a/ui/ui-graphics/api/0.1.0-dev14.txt
+++ b/ui/ui-graphics/api/0.1.0-dev14.txt
@@ -18,7 +18,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -33,7 +32,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -54,7 +53,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -133,10 +132,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -291,6 +290,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -383,7 +383,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -404,7 +404,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -469,18 +469,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -725,41 +725,41 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -777,9 +777,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -792,7 +792,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -829,7 +829,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1239,7 +1239,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/api/current.txt b/ui/ui-graphics/api/current.txt
index db17451..1ded5ae 100644
--- a/ui/ui-graphics/api/current.txt
+++ b/ui/ui-graphics/api/current.txt
@@ -18,7 +18,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -33,7 +32,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -54,7 +53,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -133,10 +132,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -291,6 +290,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -383,7 +383,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -404,7 +404,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -469,18 +469,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -725,41 +725,41 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -777,9 +777,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -792,7 +792,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -829,7 +829,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1239,7 +1239,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev14.txt
index db17451..1ded5ae 100644
--- a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev14.txt
@@ -18,7 +18,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -33,7 +32,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -54,7 +53,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -133,10 +132,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -291,6 +290,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -383,7 +383,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -404,7 +404,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -469,18 +469,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -725,41 +725,41 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -777,9 +777,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -792,7 +792,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -829,7 +829,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1239,7 +1239,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/api/public_plus_experimental_current.txt b/ui/ui-graphics/api/public_plus_experimental_current.txt
index db17451..1ded5ae 100644
--- a/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -18,7 +18,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -33,7 +32,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -54,7 +53,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -133,10 +132,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -291,6 +290,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -383,7 +383,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -404,7 +404,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -469,18 +469,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -725,41 +725,41 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -777,9 +777,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -792,7 +792,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -829,7 +829,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1239,7 +1239,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/api/restricted_0.1.0-dev14.txt b/ui/ui-graphics/api/restricted_0.1.0-dev14.txt
index 72eb329..6602759 100644
--- a/ui/ui-graphics/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-graphics/api/restricted_0.1.0-dev14.txt
@@ -20,10 +20,10 @@
     method public void concat(androidx.ui.graphics.vectormath.Matrix4 matrix4);
     method public void disableZ();
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize, long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize, androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
     method public void drawPoints(androidx.ui.graphics.PointMode pointMode, java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.Paint paint);
@@ -50,7 +50,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -65,7 +64,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -86,7 +85,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -165,10 +164,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -324,6 +323,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -416,7 +416,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -437,7 +437,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -502,18 +502,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -758,42 +758,42 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
     method @kotlin.PublishedApi internal final void setSize-b2zCL34(long size);
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -813,9 +813,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -828,7 +828,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -865,7 +865,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1275,7 +1275,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/api/restricted_current.txt b/ui/ui-graphics/api/restricted_current.txt
index 72eb329..6602759 100644
--- a/ui/ui-graphics/api/restricted_current.txt
+++ b/ui/ui-graphics/api/restricted_current.txt
@@ -20,10 +20,10 @@
     method public void concat(androidx.ui.graphics.vectormath.Matrix4 matrix4);
     method public void disableZ();
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize, long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize, androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
     method public void drawPoints(androidx.ui.graphics.PointMode pointMode, java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.Paint paint);
@@ -50,7 +50,6 @@
   }
 
   public final class AndroidImageAssetKt {
-    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static android.graphics.Bitmap asAndroidBitmap(androidx.ui.graphics.ImageAsset);
     method public static androidx.ui.graphics.ImageAsset asImageAsset(android.graphics.Bitmap);
     method public static androidx.ui.graphics.ImageAsset imageFromResource(android.content.res.Resources res, int resId);
@@ -65,7 +64,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -86,7 +85,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public androidx.ui.graphics.PathFillType fillType;
     property public boolean isConvex;
     property public boolean isEmpty;
@@ -165,10 +164,10 @@
     method public default void drawArc(androidx.ui.geometry.Rect rect, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.graphics.Paint paint);
     method public default void drawArcRad(androidx.ui.geometry.Rect rect, float startAngleRad, float sweepAngleRad, boolean useCenter, androidx.ui.graphics.Paint paint);
-    method public void drawCircle-NfwrgZA(long center, float radius, androidx.ui.graphics.Paint paint);
-    method public void drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset image, long topLeftOffset, androidx.ui.graphics.Paint paint);
-    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
-    method public void drawLine-d9kBv1M(long p1, long p2, androidx.ui.graphics.Paint paint);
+    method public void drawCircle(androidx.ui.geometry.Offset center, float radius, androidx.ui.graphics.Paint paint);
+    method public void drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeftOffset, androidx.ui.graphics.Paint paint);
+    method public void drawImageRect-btuv3no(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset, long dstSize, androidx.ui.graphics.Paint paint);
+    method public void drawLine(androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.Paint paint);
     method public default void drawOval(androidx.ui.geometry.Rect rect, androidx.ui.graphics.Paint paint);
     method public void drawOval(float left, float top, float right, float bottom, androidx.ui.graphics.Paint paint);
     method public void drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Paint paint);
@@ -324,6 +323,7 @@
   }
 
   public final class ImageAssetKt {
+    method public static androidx.ui.graphics.ImageAsset ImageAsset(int width, int height, androidx.ui.graphics.ImageAssetConfig config = androidx.ui.graphics.ImageAssetConfig.Argb8888, boolean hasAlpha = true, androidx.ui.graphics.colorspace.ColorSpace colorSpace = ColorSpaces.Srgb);
     method public static androidx.ui.graphics.PixelMap toPixelMap(androidx.ui.graphics.ImageAsset, int startX = 0, int startY = 0, int width = this.width, int height = this.height, int[] buffer = null(width * height), int bufferOffset = 0, int stride = width);
   }
 
@@ -416,7 +416,7 @@
     method public void addArc(androidx.ui.geometry.Rect oval, float startAngleDegrees, float sweepAngleDegrees);
     method public void addArcRad(androidx.ui.geometry.Rect oval, float startAngleRadians, float sweepAngleRadians);
     method public void addOval(androidx.ui.geometry.Rect oval);
-    method public void addPath-m3TnucA(androidx.ui.graphics.Path path, long offset = Offset.zero);
+    method public void addPath(androidx.ui.graphics.Path path, androidx.ui.geometry.Offset offset = Offset.Zero);
     method public void addRRect(androidx.ui.geometry.RRect rrect);
     method public void addRect(androidx.ui.geometry.Rect rect);
     method public void arcTo(androidx.ui.geometry.Rect rect, float startAngleDegrees, float sweepAngleDegrees, boolean forceMoveTo);
@@ -437,7 +437,7 @@
     method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
-    method public void shift-RIqb49o(long offset);
+    method public void shift(androidx.ui.geometry.Offset offset);
     property public abstract androidx.ui.graphics.PathFillType fillType;
     property public abstract boolean isConvex;
     property public abstract boolean isEmpty;
@@ -502,18 +502,18 @@
 
   public final class ShaderKt {
     method public static android.graphics.Shader ImageShader(androidx.ui.graphics.ImageAsset image, androidx.ui.graphics.TileMode tileModeX = androidx.ui.graphics.TileMode.Clamp, androidx.ui.graphics.TileMode tileModeY = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader LinearGradientShader-BG1VTC8(long from, long to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
-    method public static android.graphics.Shader RadialGradientShader-nSjqbmE(long center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader LinearGradientShader(androidx.ui.geometry.Offset from, androidx.ui.geometry.Offset to, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
+    method public static android.graphics.Shader RadialGradientShader(androidx.ui.geometry.Offset center, float radius, java.util.List<androidx.ui.graphics.Color> colors, java.util.List<java.lang.Float>? colorStops = null, androidx.ui.graphics.TileMode tileMode = androidx.ui.graphics.TileMode.Clamp);
   }
 
   @androidx.compose.Immutable public final class Shadow {
     method public long component1();
-    method public long component2();
+    method public androidx.ui.geometry.Offset component2();
     method public float component3();
-    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, long offset, float blurRadius);
+    method @androidx.compose.Immutable public androidx.ui.graphics.Shadow copy-hgWLwZA(long color, androidx.ui.geometry.Offset offset, float blurRadius);
     method public float getBlurRadius();
     method public long getColor();
-    method public long getOffset();
+    method public androidx.ui.geometry.Offset getOffset();
     field public static final androidx.ui.graphics.Shadow.Companion! Companion;
   }
 
@@ -758,42 +758,42 @@
   @androidx.ui.graphics.drawscope.DrawScopeMarker public interface CanvasTransform {
     method public void clipPath(androidx.ui.graphics.Path path, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
     method public void clipRect(float left = 0.0f, float top = 0.0f, float right = size.width, float bottom = size.height, androidx.ui.graphics.ClipOp clipOp = androidx.ui.graphics.ClipOp.intersect);
-    method public default long getCenter();
+    method public default androidx.ui.geometry.Offset getCenter();
     method public long getSize();
     method public void inset(float left, float top, float right, float bottom);
-    method public void rotate(float degrees, float pivotX = center.dx, float pivotY = center.dy);
-    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy);
+    method public void rotate(float degrees, float pivotX = center.x, float pivotY = center.y);
+    method public void scale(float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y);
     method public void translate(float left = 0.0f, float top = 0.0f);
-    property public default long center;
+    property public default androidx.ui.geometry.Offset center;
     property public abstract long size;
   }
 
   @androidx.ui.graphics.drawscope.DrawScopeMarker public abstract class DrawScope implements androidx.ui.unit.Density {
     ctor public DrawScope();
     method public final void draw-mEaFHtM(androidx.ui.graphics.Canvas canvas, long size, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawCircle-nE2_nkE(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, long center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, long srcOffset = Offset.zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), long dstOffset = Offset.zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawImage-p3XzKf0(androidx.ui.graphics.ImageAsset image, long topLeft = Offset.zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawLine-p3tcZP4(androidx.ui.graphics.Brush brush, long p1, long p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-MKXvu20(androidx.ui.graphics.Brush brush, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawArc-w9iw49s(long color, float startAngle, float sweepAngle, boolean useCenter, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle(androidx.ui.graphics.Brush brush, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawCircle-UNeD5NE(long color, float radius = size.minDimension / 2.0, androidx.ui.geometry.Offset center = this.center, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset topLeft = Offset.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawImage-SM7YF0Q(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset = Offset.Zero, long srcSize = Size(image.width.toFloat(), image.height.toFloat()), androidx.ui.geometry.Offset dstOffset = Offset.Zero, long dstSize = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawLine-SuN1Ejc(long color, androidx.ui.geometry.Offset p1, androidx.ui.geometry.Offset p2, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawOval-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath(androidx.ui.graphics.Path path, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPath-u5ZPEDk(androidx.ui.graphics.Path path, long color, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, androidx.ui.graphics.Brush brush, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
     method public final kotlin.Unit? drawPoints-kayC28I(java.util.List<androidx.ui.geometry.Offset> points, androidx.ui.graphics.PointMode pointMode, long color, androidx.ui.graphics.drawscope.Stroke stroke, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-5gW23P0(long color, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-4SUkJp4(androidx.ui.graphics.Brush brush, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = radiusX, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final kotlin.Unit? drawRoundRect-JepXTL0(long color, long topLeft = Offset.zero, long size = this.size, float radiusX = 0.0f, float radiusY = 0.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
-    method public final long getCenter();
+    method public final kotlin.Unit? drawRect-5gW23P0(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRect-m7aN-JY(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-J_jAawI(long color, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, androidx.ui.graphics.drawscope.DrawStyle style = Fill, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final kotlin.Unit? drawRoundRect-TLscAYA(androidx.ui.graphics.Brush brush, androidx.ui.geometry.Offset topLeft = Offset.Zero, long size = this.size, long radius = Radius.Zero, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.drawscope.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = DefaultBlendMode);
+    method public final androidx.ui.geometry.Offset getCenter();
     method public abstract androidx.ui.core.LayoutDirection getLayoutDirection();
     method public final long getSize();
     method @kotlin.PublishedApi internal final void setSize-b2zCL34(long size);
-    property public final long center;
+    property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final long size;
     field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
@@ -813,9 +813,9 @@
     method public static inline kotlin.Unit? drawCanvas(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function2<? super androidx.ui.graphics.Canvas,? super androidx.ui.geometry.Size,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float left, float top, float right, float bottom, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? inset(androidx.ui.graphics.drawscope.DrawScope, float dx = 0.0f, float dy = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
-    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.dx, float pivotY = center.dy, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotate(androidx.ui.graphics.drawscope.DrawScope, float degrees, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? rotateRad(androidx.ui.graphics.drawscope.DrawScope, float radians, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
+    method public static inline androidx.ui.graphics.Canvas? scale(androidx.ui.graphics.drawscope.DrawScope, float scaleX, float scaleY = scaleX, float pivotX = center.x, float pivotY = center.y, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? translate(androidx.ui.graphics.drawscope.DrawScope, float left = 0.0f, float top = 0.0f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> block);
     method public static inline androidx.ui.graphics.Canvas? withTransform(androidx.ui.graphics.drawscope.DrawScope, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.CanvasTransform,kotlin.Unit> transformBlock, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.drawscope.DrawScope,kotlin.Unit> drawBlock);
   }
@@ -828,7 +828,7 @@
 
   public final class DrawTransformKt {
     method public static inline void inset(androidx.ui.graphics.drawscope.CanvasTransform, float dx = 0.0f, float dy = 0.0f);
-    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.dx, float pivotY = center.dy);
+    method public static inline void rotateRad(androidx.ui.graphics.drawscope.CanvasTransform, float radians, float pivotX = center.x, float pivotY = center.y);
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -865,7 +865,7 @@
   }
 
   public final class ImagePainter extends androidx.ui.graphics.painter.Painter {
-    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, long srcOffset, long srcSize);
+    method public androidx.ui.graphics.painter.ImagePainter copy-gqgapXI(androidx.ui.graphics.ImageAsset image, androidx.ui.geometry.Offset srcOffset, long srcSize);
     method public long getIntrinsicSize();
     method protected void onDraw(androidx.ui.graphics.drawscope.DrawScope);
     property public long intrinsicSize;
@@ -1275,7 +1275,7 @@
     method public static androidx.ui.geometry.Rect inverseTransformRect(androidx.ui.graphics.vectormath.Matrix4 transform, androidx.ui.geometry.Rect rect);
     method public static boolean isIdentity(androidx.ui.graphics.vectormath.Matrix4);
     method public static boolean matrixEquals(androidx.ui.graphics.vectormath.Matrix4? a, androidx.ui.graphics.vectormath.Matrix4? b);
-    method public static long transformPoint-k2M_ft0(androidx.ui.graphics.vectormath.Matrix4, long point);
+    method public static androidx.ui.geometry.Offset transformPoint(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Offset point);
     method public static androidx.ui.geometry.Rect transformRect(androidx.ui.graphics.vectormath.Matrix4, androidx.ui.geometry.Rect rect);
   }
 
diff --git a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/AndroidCanvasTest.kt b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/AndroidCanvasTest.kt
index 8c7846f..bfcd3af 100644
--- a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/AndroidCanvasTest.kt
+++ b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/AndroidCanvasTest.kt
@@ -27,7 +27,6 @@
 import android.widget.FrameLayout
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.geometry.Rect
 import androidx.ui.test.captureToBitmap
 import org.junit.Assert.assertEquals
@@ -43,8 +42,9 @@
 @MediumTest
 @RunWith(JUnit4::class)
 class AndroidCanvasTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
 
diff --git a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/painter/ImagePainterTest.kt b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/painter/ImagePainterTest.kt
index 26dfd81..ca4cdf8 100644
--- a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/painter/ImagePainterTest.kt
+++ b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/painter/ImagePainterTest.kt
@@ -134,7 +134,7 @@
         val canvas = Canvas(dst)
 
         val topLeftPainter = ImagePainter(srcImage,
-            srcOffset = Offset.zero,
+            srcOffset = Offset.Zero,
             srcSize = Size(50.0f, 50.0f)
         )
 
diff --git a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidCanvas.kt b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidCanvas.kt
index e86b2d6..acecd0e 100644
--- a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidCanvas.kt
+++ b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidCanvas.kt
@@ -188,10 +188,10 @@
      */
     override fun drawLine(p1: Offset, p2: Offset, paint: Paint) {
         internalCanvas.drawLine(
-            p1.dx,
-            p1.dy,
-            p2.dx,
-            p2.dy,
+            p1.x,
+            p1.y,
+            p2.x,
+            p2.y,
             paint.asFrameworkPaint()
         )
     }
@@ -229,8 +229,8 @@
      */
     override fun drawCircle(center: Offset, radius: Float, paint: Paint) {
         internalCanvas.drawCircle(
-            center.dx,
-            center.dy,
+            center.x,
+            center.y,
             radius,
             paint.asFrameworkPaint()
         )
@@ -271,8 +271,8 @@
     override fun drawImage(image: ImageAsset, topLeftOffset: Offset, paint: Paint) {
         internalCanvas.drawBitmap(
             image.asAndroidBitmap(),
-            topLeftOffset.dx,
-            topLeftOffset.dy,
+            topLeftOffset.x,
+            topLeftOffset.y,
             paint.asFrameworkPaint()
         )
     }
@@ -294,16 +294,16 @@
         internalCanvas.drawBitmap(
             image.asAndroidBitmap(),
             srcRect.apply {
-                left = srcOffset.dx.toInt()
-                top = srcOffset.dy.toInt()
-                right = (srcOffset.dx + srcSize.width).toInt()
-                bottom = (srcOffset.dy + srcSize.height).toInt()
+                left = srcOffset.x.toInt()
+                top = srcOffset.y.toInt()
+                right = (srcOffset.x + srcSize.width).toInt()
+                bottom = (srcOffset.y + srcSize.height).toInt()
             },
             dstRect.apply {
-                left = dstOffset.dx.toInt()
-                top = dstOffset.dy.toInt()
-                right = (dstOffset.dx + dstSize.width).toInt()
-                bottom = (dstOffset.dy + dstSize.height).toInt()
+                left = dstOffset.x.toInt()
+                top = dstOffset.y.toInt()
+                right = (dstOffset.x + dstSize.width).toInt()
+                bottom = (dstOffset.y + dstSize.height).toInt()
             },
             paint.asFrameworkPaint()
         )
@@ -337,8 +337,8 @@
     private fun drawPoints(points: List<Offset>, paint: Paint) {
         points.fastForEach { point ->
             internalCanvas.drawPoint(
-                point.dx,
-                point.dy,
+                point.x,
+                point.y,
                 paint.asFrameworkPaint()
             )
         }
@@ -362,10 +362,10 @@
                 val p1 = points[i]
                 val p2 = points[i + 1]
                 internalCanvas.drawLine(
-                    p1.dx,
-                    p1.dy,
-                    p2.dx,
-                    p2.dy,
+                    p1.x,
+                    p1.y,
+                    p2.x,
+                    p2.y,
                     paint.asFrameworkPaint()
                 )
             }
diff --git a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidImageAsset.kt b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidImageAsset.kt
index 021df4b..fb6e987 100644
--- a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidImageAsset.kt
+++ b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidImageAsset.kt
@@ -45,12 +45,12 @@
  */
 fun Bitmap.asImageAsset(): ImageAsset = AndroidImageAsset(this)
 
-/* actual */ fun ImageAsset(
+internal actual fun ActualImageAsset(
     width: Int,
     height: Int,
-    config: ImageAssetConfig = ImageAssetConfig.Argb8888,
-    hasAlpha: Boolean = true,
-    colorSpace: ColorSpace = ColorSpaces.Srgb
+    config: ImageAssetConfig,
+    hasAlpha: Boolean,
+    colorSpace: ColorSpace
 ): ImageAsset {
     val bitmapConfig = config.toBitmapConfig()
     val bitmap: Bitmap
diff --git a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
index 9722bd4..4025d38 100644
--- a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
+++ b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
@@ -169,7 +169,7 @@
     }
 
     override fun addPath(path: Path, offset: Offset) {
-        internalPath.addPath(path.asAndroidPath(), offset.dx, offset.dy)
+        internalPath.addPath(path.asAndroidPath(), offset.x, offset.y)
     }
 
     override fun close() {
@@ -182,7 +182,7 @@
 
     override fun shift(offset: Offset) {
         mMatrix.reset()
-        mMatrix.setTranslate(offset.dx, offset.dy)
+        mMatrix.setTranslate(offset.x, offset.y)
         internalPath.transform(mMatrix)
     }
 
diff --git a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidShader.kt b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidShader.kt
index 9972694..dcbbfbb 100644
--- a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidShader.kt
+++ b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidShader.kt
@@ -33,10 +33,10 @@
     validateColorStops(colors, colorStops)
     return Shader(
         LinearGradient(
-            from.dx,
-            from.dy,
-            to.dx,
-            to.dy,
+            from.x,
+            from.y,
+            to.x,
+            to.y,
             colors.toIntArray(),
             colorStops?.toFloatArray(),
             tileMode.toNativeTileMode()
@@ -54,8 +54,8 @@
     validateColorStops(colors, colorStops)
     return Shader(
         RadialGradient(
-            center.dx,
-            center.dy,
+            center.x,
+            center.y,
             radius,
             colors.toIntArray(),
             colorStops?.toFloatArray(),
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Canvas.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Canvas.kt
index 5dbebc7..69f3a10 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Canvas.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Canvas.kt
@@ -560,7 +560,7 @@
      */
     fun drawImageRect(
         image: ImageAsset,
-        srcOffset: Offset = Offset.zero,
+        srcOffset: Offset = Offset.Zero,
         srcSize: Size = Size(image.width.toFloat(), image.height.toFloat()),
         dstOffset: Offset,
         dstSize: Size,
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/ImageAsset.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/ImageAsset.kt
index fe28044..84d6784 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/ImageAsset.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/ImageAsset.kt
@@ -216,3 +216,25 @@
      */
     Gpu
 }
+
+internal expect fun ActualImageAsset(
+    width: Int,
+    height: Int,
+    config: ImageAssetConfig,
+    hasAlpha: Boolean,
+    colorSpace: ColorSpace
+): ImageAsset
+
+fun ImageAsset(
+    width: Int,
+    height: Int,
+    config: ImageAssetConfig = ImageAssetConfig.Argb8888,
+    hasAlpha: Boolean = true,
+    colorSpace: ColorSpace = ColorSpaces.Srgb
+): ImageAsset = ActualImageAsset(
+    width,
+    height,
+    config,
+    hasAlpha,
+    colorSpace
+)
\ No newline at end of file
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Outline.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Outline.kt
index 0526f64..61b1b9d 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Outline.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Outline.kt
@@ -19,6 +19,7 @@
 import androidx.ui.util.annotation.FloatRange
 import androidx.ui.geometry.Offset
 import androidx.ui.geometry.RRect
+import androidx.ui.geometry.Radius
 import androidx.ui.geometry.Rect
 import androidx.ui.geometry.Size
 import androidx.ui.graphics.drawscope.DrawScope
@@ -103,8 +104,7 @@
                 color = color,
                 topLeft = rrect.topLeft(),
                 size = rrect.size(),
-                radiusX = radius,
-                radiusY = radius,
+                radius = Radius(radius),
                 alpha = alpha,
                 style = style,
                 colorFilter = colorFilter,
@@ -143,8 +143,7 @@
                 brush = brush,
                 topLeft = rrect.topLeft(),
                 size = rrect.size(),
-                radiusX = radius,
-                radiusY = radius,
+                radius = Radius(radius),
                 alpha = alpha,
                 style = style,
                 colorFilter = colorFilter,
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
index 281462d..cac643c 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
@@ -207,7 +207,7 @@
      * after the matrix is translated by the given offset. The matrix is a 4x4
      * matrix stored in column major order.
      */
-    fun addPath(path: Path, offset: Offset = Offset.zero)
+    fun addPath(path: Path, offset: Offset = Offset.Zero)
 
     /**
      * Closes the last subpath, as if a straight line had been drawn
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Shadow.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Shadow.kt
index ce60cdd..29d8aaa 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Shadow.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Shadow.kt
@@ -19,6 +19,7 @@
 import androidx.compose.Immutable
 import androidx.compose.Stable
 import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import androidx.ui.util.lerp
 
 /**
@@ -29,7 +30,7 @@
     @Stable
     val color: Color = Color(0xFF000000),
     @Stable
-    val offset: Offset = Offset.zero,
+    val offset: Offset = Offset.Zero,
     @Stable
     val blurRadius: Float = 0.0f
 ) {
@@ -49,7 +50,7 @@
 fun lerp(start: Shadow, stop: Shadow, fraction: Float): Shadow {
     return Shadow(
         lerp(start.color, stop.color, fraction),
-        Offset.lerp(start.offset, stop.offset, fraction),
+        lerp(start.offset, stop.offset, fraction),
         lerp(start.blurRadius, stop.blurRadius, fraction)
     )
 }
\ No newline at end of file
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Vertices.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Vertices.kt
index deeb0f2..68cf6f8a 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Vertices.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Vertices.kt
@@ -61,9 +61,9 @@
             val pointIndex = i / 2
             val point = points[pointIndex]
             if (i % 2 == 0) {
-                point.dx
+                point.x
             } else {
-                point.dy
+                point.y
             }
         }
     }
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
index 4a4d9c6..d51f933d 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
@@ -19,6 +19,7 @@
 import androidx.ui.util.annotation.FloatRange
 import androidx.ui.core.LayoutDirection
 import androidx.ui.geometry.Offset
+import androidx.ui.geometry.Radius
 import androidx.ui.geometry.Size
 import androidx.ui.graphics.BlendMode
 import androidx.ui.graphics.Brush
@@ -111,8 +112,8 @@
  */
 inline fun DrawScope.rotate(
     degrees: Float,
-    pivotX: Float = center.dx,
-    pivotY: Float = center.dy,
+    pivotX: Float = center.x,
+    pivotY: Float = center.y,
     block: DrawScope.() -> Unit
 ) = withTransform({ rotate(degrees, pivotX, pivotY) }, block)
 
@@ -130,8 +131,8 @@
  */
 inline fun DrawScope.rotateRad(
     radians: Float,
-    pivotX: Float = center.dx,
-    pivotY: Float = center.dy,
+    pivotX: Float = center.x,
+    pivotY: Float = center.y,
     block: DrawScope.() -> Unit
 ) = withTransform({ rotate(degrees(radians), pivotX, pivotY) }, block)
 
@@ -155,8 +156,8 @@
 inline fun DrawScope.scale(
     scaleX: Float,
     scaleY: Float = scaleX,
-    pivotX: Float = center.dx,
-    pivotY: Float = center.dy,
+    pivotX: Float = center.x,
+    pivotY: Float = center.y,
     block: DrawScope.() -> Unit
 ) = withTransform({ scale(scaleX, scaleY, pivotX, pivotY) }, block)
 
@@ -413,17 +414,17 @@
      */
     fun drawRect(
         brush: Brush,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawRect(
-            left = topLeft.dx,
-            top = topLeft.dy,
-            right = topLeft.dx + size.width,
-            bottom = topLeft.dy + size.height,
+            left = topLeft.x,
+            top = topLeft.y,
+            right = topLeft.x + size.width,
+            bottom = topLeft.y + size.height,
             paint = configurePaint(brush, style, alpha, colorFilter, blendMode)
         )
 
@@ -443,17 +444,17 @@
      */
     fun drawRect(
         color: Color,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawRect(
-            left = topLeft.dx,
-            top = topLeft.dy,
-            right = topLeft.dx + size.width,
-            bottom = topLeft.dy + size.height,
+            left = topLeft.x,
+            top = topLeft.y,
+            right = topLeft.x + size.width,
+            bottom = topLeft.y + size.height,
             paint = configurePaint(color, style, alpha, colorFilter, blendMode)
         )
 
@@ -471,7 +472,7 @@
      */
     fun drawImage(
         image: ImageAsset,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
@@ -507,9 +508,9 @@
      */
     fun drawImage(
         image: ImageAsset,
-        srcOffset: Offset = Offset.zero,
+        srcOffset: Offset = Offset.Zero,
         srcSize: Size = Size(image.width.toFloat(), image.height.toFloat()),
-        dstOffset: Offset = Offset.zero,
+        dstOffset: Offset = Offset.Zero,
         dstSize: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
@@ -532,8 +533,7 @@
      * @param brush The color or fill to be applied to the rounded rectangle
      * @param topLeft Offset from the local origin of 0, 0 relative to the current translation
      * @param size Dimensions of the rectangle to draw
-     * @param radiusX Corner radius of the rounded rectangle along the x-axis
-     * @param radiusY Corner radius of the rounded rectangle along the y-axis
+     * @param radius Corner radius of the rounded rectangle
      * @param alpha Opacity to be applied to rounded rectangle from 0.0f to 1.0f representing
      * fully transparent to fully opaque respectively
      * @param style Specifies whether the rounded rectangle is stroked or filled in
@@ -542,21 +542,20 @@
      */
     fun drawRoundRect(
         brush: Brush,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
-        radiusX: Float = 0.0f,
-        radiusY: Float = radiusX,
+        radius: Radius = Radius.Zero,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawRoundRect(
-            topLeft.dx,
-            topLeft.dy,
-            topLeft.dx + size.width,
-            topLeft.dy + size.height,
-            radiusX,
-            radiusY,
+            topLeft.x,
+            topLeft.y,
+            topLeft.x + size.width,
+            topLeft.y + size.height,
+            radius.x,
+            radius.y,
             configurePaint(brush, style, alpha, colorFilter, blendMode)
         )
 
@@ -567,8 +566,7 @@
      * @param color The color to be applied to the rounded rectangle
      * @param topLeft Offset from the local origin of 0, 0 relative to the current translation
      * @param size Dimensions of the rectangle to draw
-     * @param radiusX Corner radius of the rounded rectangle along the x-axis
-     * @param radiusY Corner radius of the rounded rectangle along the y-axis
+     * @param radius Corner radius of the rounded rectangle
      * @param alpha Opacity to be applied to rounded rectangle from 0.0f to 1.0f representing
      * fully transparent to fully opaque respectively
      * @param style Specifies whether the rounded rectangle is stroked or filled in
@@ -577,21 +575,20 @@
      */
     fun drawRoundRect(
         color: Color,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
-        radiusX: Float = 0.0f,
-        radiusY: Float = 0.0f,
+        radius: Radius = Radius.Zero,
         style: DrawStyle = Fill,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawRoundRect(
-            topLeft.dx,
-            topLeft.dy,
-            topLeft.dx + size.width,
-            topLeft.dy + size.height,
-            radiusX,
-            radiusY,
+            topLeft.x,
+            topLeft.y,
+            topLeft.x + size.width,
+            topLeft.y + size.height,
+            radius.x,
+            radius.y,
             configurePaint(color, style, alpha, colorFilter, blendMode)
         )
 
@@ -665,17 +662,17 @@
      */
     fun drawOval(
         brush: Brush,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawOval(
-            left = topLeft.dx,
-            top = topLeft.dy,
-            right = topLeft.dx + size.width,
-            bottom = topLeft.dy + size.height,
+            left = topLeft.x,
+            top = topLeft.y,
+            right = topLeft.x + size.width,
+            bottom = topLeft.y + size.height,
             paint = configurePaint(brush, style, alpha, colorFilter, blendMode)
         )
 
@@ -695,17 +692,17 @@
      */
     fun drawOval(
         color: Color,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawOval(
-            left = topLeft.dx,
-            top = topLeft.dy,
-            right = topLeft.dx + size.width,
-            bottom = topLeft.dy + size.height,
+            left = topLeft.x,
+            top = topLeft.y,
+            right = topLeft.x + size.width,
+            bottom = topLeft.y + size.height,
             paint = configurePaint(color, style, alpha, colorFilter, blendMode)
         )
 
@@ -737,17 +734,17 @@
         startAngle: Float,
         sweepAngle: Float,
         useCenter: Boolean,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawArc(
-            left = topLeft.dx,
-            top = topLeft.dy,
-            right = topLeft.dx + size.width,
-            bottom = topLeft.dy + size.height,
+            left = topLeft.x,
+            top = topLeft.y,
+            right = topLeft.x + size.width,
+            bottom = topLeft.y + size.height,
             startAngle = startAngle,
             sweepAngle = sweepAngle,
             useCenter = useCenter,
@@ -782,17 +779,17 @@
         startAngle: Float,
         sweepAngle: Float,
         useCenter: Boolean,
-        topLeft: Offset = Offset.zero,
+        topLeft: Offset = Offset.Zero,
         size: Size = this.size,
         @FloatRange(from = 0.0, to = 1.0) alpha: Float = DefaultAlpha,
         style: DrawStyle = Fill,
         colorFilter: ColorFilter? = null,
         blendMode: BlendMode = DefaultBlendMode
     ) = canvas?.drawArc(
-        left = topLeft.dx,
-        top = topLeft.dy,
-        right = topLeft.dx + size.width,
-        bottom = topLeft.dy + size.height,
+        left = topLeft.x,
+        top = topLeft.y,
+        right = topLeft.x + size.width,
+        bottom = topLeft.y + size.height,
         startAngle = startAngle,
         sweepAngle = sweepAngle,
         useCenter = useCenter,
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawTransform.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawTransform.kt
index d09b05f..26be071 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawTransform.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawTransform.kt
@@ -47,8 +47,8 @@
 @Suppress("NOTHING_TO_INLINE")
 inline fun CanvasTransform.rotateRad(
     radians: Float,
-    pivotX: Float = center.dx,
-    pivotY: Float = center.dy
+    pivotX: Float = center.x,
+    pivotY: Float = center.y
 ) = rotate(degrees(radians), pivotX, pivotY)
 
 /**
@@ -131,7 +131,7 @@
      *  @param pivotY The y-coordinate for the pivot point, defaults to the center of the
      *  coordinate space vertically
      */
-    fun rotate(degrees: Float, pivotX: Float = center.dx, pivotY: Float = center.dy)
+    fun rotate(degrees: Float, pivotX: Float = center.x, pivotY: Float = center.y)
 
     /**
      * Add an axis-aligned scale to the current transform, scaling by the first
@@ -152,7 +152,7 @@
     fun scale(
         scaleX: Float,
         scaleY: Float = scaleX,
-        pivotX: Float = center.dx,
-        pivotY: Float = center.dy
+        pivotX: Float = center.x,
+        pivotY: Float = center.y
     )
 }
\ No newline at end of file
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/painter/ImagePainter.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/painter/ImagePainter.kt
index c991b9b..e9c6726 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/painter/ImagePainter.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/painter/ImagePainter.kt
@@ -38,7 +38,7 @@
  */
 data class ImagePainter(
     private val image: ImageAsset,
-    private val srcOffset: Offset = Offset.zero,
+    private val srcOffset: Offset = Offset.Zero,
     private val srcSize: Size = Size(image.width.toFloat(), image.height.toFloat())
 ) : Painter() {
 
@@ -75,8 +75,8 @@
 
     private fun validateSize(srcOffset: Offset, srcSize: Size): Size {
         require(
-            srcOffset.dx >= 0 &&
-            srcOffset.dy >= 0 &&
+            srcOffset.x >= 0 &&
+            srcOffset.y >= 0 &&
             srcSize.width >= 0 &&
             srcSize.height >= 0 &&
             srcSize.width <= image.width &&
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vectormath/Matrix4.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vectormath/Matrix4.kt
index 29fe766..c0fc9b9e 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vectormath/Matrix4.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vectormath/Matrix4.kt
@@ -612,7 +612,7 @@
  * z-coordinate of the result is ignored.
  */
 fun Matrix4.transformPoint(point: Offset): Offset {
-    val position3 = Vector3(point.dx, point.dy, 0.0f)
+    val position3 = Vector3(point.x, point.y, 0.0f)
     val transformed3 = perspectiveTransform(position3)
     return Offset(transformed3.x, transformed3.y)
 }
@@ -631,10 +631,10 @@
     val point3 = transformPoint(rect.getBottomLeft())
     val point4 = transformPoint(rect.getBottomRight())
     return Rect.fromLTRB(
-        min4(point1.dx, point2.dx, point3.dx, point4.dx),
-        min4(point1.dy, point2.dy, point3.dy, point4.dy),
-        max4(point1.dx, point2.dx, point3.dx, point4.dx),
-        max4(point1.dy, point2.dy, point3.dy, point4.dy)
+        min4(point1.x, point2.x, point3.x, point4.x),
+        min4(point1.y, point2.y, point3.y, point4.y),
+        max4(point1.x, point2.x, point3.x, point4.x),
+        max4(point1.y, point2.y, point3.y, point4.y)
     )
 }
 
diff --git a/ui/ui-graphics/src/test/java/androidx/ui/graphics/ShadowTest.kt b/ui/ui-graphics/src/test/java/androidx/ui/graphics/ShadowTest.kt
index a5660ca..da7b419 100644
--- a/ui/ui-graphics/src/test/java/androidx/ui/graphics/ShadowTest.kt
+++ b/ui/ui-graphics/src/test/java/androidx/ui/graphics/ShadowTest.kt
@@ -17,6 +17,7 @@
 package androidx.ui.painting
 
 import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.Shadow
 import androidx.ui.graphics.lerp
@@ -34,7 +35,7 @@
         val shadow = Shadow()
         assertThat(shadow.color, equalTo(Color(0xFF000000)))
         assertThat(shadow.blurRadius, equalTo(0.0f))
-        assertThat(shadow.offset, equalTo(Offset.zero))
+        assertThat(shadow.offset, equalTo(Offset.Zero))
     }
 
     @Test
@@ -63,7 +64,7 @@
 
         val shadow = lerp(shadowA, shadowB, t)
         assertThat(shadow.color, equalTo(lerp(colorA, colorB, t)))
-        assertThat(shadow.offset, equalTo(Offset.lerp(offsetA, offsetB, t)))
+        assertThat(shadow.offset, equalTo(lerp(offsetA, offsetB, t)))
         assertThat(shadow.blurRadius, equalTo(lerp(radiusA, radiusB, t)))
     }
 }
\ No newline at end of file
diff --git a/ui/ui-layout/api/0.1.0-dev14.txt b/ui/ui-layout/api/0.1.0-dev14.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/0.1.0-dev14.txt
+++ b/ui/ui-layout/api/0.1.0-dev14.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/api/api_lint.ignore b/ui/ui-layout/api/api_lint.ignore
index d7bb8be..945436c 100644
--- a/ui/ui-layout/api/api_lint.ignore
+++ b/ui/ui-layout/api/api_lint.ignore
@@ -1,3 +1,27 @@
 // Baseline format: 1.0
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference[], androidx.ui.layout.ChainStyle) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference[], float) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+ArrayReturn: androidx.ui.layout.ConstraintLayoutBaseScope#createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference[], androidx.ui.layout.ChainStyle) parameter #0:
+    Method parameter should be Collection<ConstrainedLayoutReference> (or subclass) instead of raw array; was `androidx.ui.layout.ConstrainedLayoutReference[]`
+
+
 HiddenTypeParameter: androidx.ui.layout.Arrangement#Companion:
     Field Arrangement.Companion references hidden type androidx.ui.layout.Arrangement.Companion.
+
+
+MutableBareField: androidx.ui.layout.State#layoutDirection:
+    Bare field layoutDirection must be marked final, or moved behind accessors if mutable
+MutableBareField: androidx.ui.layout.State#rootIncomingConstraints:
+    Bare field rootIncomingConstraints must be marked final, or moved behind accessors if mutable
diff --git a/ui/ui-layout/api/current.txt b/ui/ui-layout/api/current.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/current.txt
+++ b/ui/ui-layout/api/current.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev14.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev14.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/api/public_plus_experimental_current.txt b/ui/ui-layout/api/public_plus_experimental_current.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/public_plus_experimental_current.txt
+++ b/ui/ui-layout/api/public_plus_experimental_current.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/api/restricted_0.1.0-dev14.txt b/ui/ui-layout/api/restricted_0.1.0-dev14.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-layout/api/restricted_0.1.0-dev14.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/api/restricted_current.txt b/ui/ui-layout/api/restricted_current.txt
index 8b810dc..7bbe3ad 100644
--- a/ui/ui-layout/api/restricted_current.txt
+++ b/ui/ui-layout/api/restricted_current.txt
@@ -57,6 +57,20 @@
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
+  public final class ChainStyle {
+    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+  }
+
+  public static final class ChainStyle.Companion {
+    method public androidx.ui.layout.ChainStyle Packed(float bias);
+    method public androidx.ui.layout.ChainStyle getPacked();
+    method public androidx.ui.layout.ChainStyle getSpread();
+    method public androidx.ui.layout.ChainStyle getSpreadInside();
+    property public final androidx.ui.layout.ChainStyle Packed;
+    property public final androidx.ui.layout.ChainStyle Spread;
+    property public final androidx.ui.layout.ChainStyle SpreadInside;
+  }
+
   public final class ColumnKt {
     method @androidx.compose.Composable public static void Column(androidx.ui.core.Modifier modifier = Modifier, androidx.ui.layout.Arrangement.Vertical verticalArrangement = Arrangement.Top, androidx.ui.core.Alignment.Horizontal horizontalGravity = Alignment.Start, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> children);
   }
@@ -69,46 +83,185 @@
     field public static final androidx.ui.layout.ColumnScope! INSTANCE;
   }
 
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor);
+    method public void centerAround(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor);
+    method public void centerHorizontallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public void centerVerticallyTo(androidx.ui.layout.ConstrainedLayoutReference other);
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteLeft();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getAbsoluteRight();
+    method public androidx.ui.layout.ConstrainScope.BaselineAnchorable getBaseline();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getBottom();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getEnd();
+    method public androidx.ui.layout.Dimension getHeight();
+    method public androidx.ui.layout.ConstrainedLayoutReference getParent();
+    method public androidx.ui.layout.ConstrainScope.VerticalAnchorable getStart();
+    method public androidx.ui.layout.ConstrainScope.HorizontalAnchorable getTop();
+    method public androidx.ui.layout.Dimension getWidth();
+    method public void linkTo-MrnifDM(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, float startMargin = 0.dp, float endMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-h2XOreo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float topMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float bias = 0.5f);
+    method public void linkTo-tsa2a54(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top, androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end, androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom, float startMargin = 0.dp, float topMargin = 0.dp, float endMargin = 0.dp, float bottomMargin = 0.dp, @FloatRange(from=0.0, to=1.0) float horizontalBias = 0.5f, @FloatRange(from=0.0, to=1.0) float verticalBias = 0.5f);
+    method public void setHeight(androidx.ui.layout.Dimension value);
+    method public void setWidth(androidx.ui.layout.Dimension value);
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteLeft;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable absoluteRight;
+    property public final androidx.ui.layout.ConstrainScope.BaselineAnchorable baseline;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable bottom;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable end;
+    property public final androidx.ui.layout.Dimension height;
+    property public final androidx.ui.layout.ConstrainedLayoutReference parent;
+    property public final androidx.ui.layout.ConstrainScope.VerticalAnchorable start;
+    property public final androidx.ui.layout.ConstrainScope.HorizontalAnchorable top;
+    property public final androidx.ui.layout.Dimension width;
+  }
+
+  public final class ConstrainScope.BaselineAnchorable {
+    method public void linkTo-oRbSkj8(androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.HorizontalAnchorable {
+    method public void linkTo-TJhmEpo(androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainScope.VerticalAnchorable {
+    method public void linkTo-sp3QI2o(androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor anchor, float margin = 0.dp);
+  }
+
+  public final class ConstrainedLayoutReference {
+    ctor public ConstrainedLayoutReference(Object tag);
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteLeft();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getAbsoluteRight();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor getBaseline();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getBottom();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getEnd();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor getStart();
+    method public Object getTag();
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor getTop();
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteLeft;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor absoluteRight;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor baseline;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor bottom;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor end;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor start;
+    property public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor top;
+  }
+
+  public abstract class ConstraintLayoutBaseScope {
+    ctor public ConstraintLayoutBaseScope();
+    method public final void applyTo(androidx.ui.layout.State state);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteLeftBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createAbsoluteRightBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createBottomBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createEndBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteLeft-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromAbsoluteRight-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromEnd-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createGuidelineFromStart-ipo6vVg(float offset);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop(float fraction);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method public final void createHorizontalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor createStartBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor createTopBarrier-AuEMxJ0(androidx.ui.layout.ConstrainedLayoutReference![] elements, float margin = 0.dp);
+    method public final void createVerticalChain(androidx.ui.layout.ConstrainedLayoutReference![] elements, androidx.ui.layout.ChainStyle chainStyle = ChainStyle.Spread);
+    method protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> getTasks();
+    method public final void reset();
+    property protected final java.util.List<kotlin.jvm.functions.Function1<androidx.ui.layout.State,kotlin.Unit>> tasks;
+  }
+
+  public static final class ConstraintLayoutBaseScope.BaselineAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.BaselineAnchor copy(Object tag);
+  }
+
+  public static final class ConstraintLayoutBaseScope.HorizontalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.HorizontalAnchor copy(Object tag, int index);
+  }
+
+  public static final class ConstraintLayoutBaseScope.VerticalAnchor {
+    method public androidx.ui.layout.ConstraintLayoutBaseScope.VerticalAnchor copy(Object tag, int index);
+  }
+
   public final class ConstraintLayoutKt {
-    method @androidx.compose.Composable @androidx.ui.layout.ExperimentalLayout public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintLayoutScope,kotlin.Unit> children);
+    method @androidx.compose.Composable public static void ConstraintLayout(androidx.ui.layout.ConstraintSet constraintSet, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated public static androidx.ui.layout.ConstraintSet ConstraintSet(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.ConstraintSet ConstraintSet2(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetScope,kotlin.Unit> description);
+    method public static androidx.ui.layout.Dimension.MaxCoercible atLeast-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atLeastWrapContent-pX8Pf4s(androidx.ui.layout.Dimension.MinCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MinCoercible atMost-UKaBGfc(androidx.ui.layout.Dimension.Coercible, float dp);
+    method public static androidx.ui.layout.Dimension atMost-bf1TpX8(androidx.ui.layout.Dimension.MaxCoercible, float dp);
+    method public static androidx.ui.layout.Dimension.MaxCoercible getAtLeastWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtLeastWrapContent(androidx.ui.layout.Dimension.MinCoercible);
+    method public static androidx.ui.layout.Dimension.MinCoercible getAtMostWrapContent(androidx.ui.layout.Dimension.Coercible);
+    method public static androidx.ui.layout.Dimension getAtMostWrapContent(androidx.ui.layout.Dimension.MaxCoercible);
   }
 
-  @androidx.compose.Immutable public final class ConstraintSet {
-    ctor public ConstraintSet(internal kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
-    method @androidx.compose.Immutable public androidx.ui.layout.ConstraintSet copy(kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstraintSetBuilderScope,kotlin.Unit> description);
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintLayoutScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.core.Modifier constrainAs(androidx.ui.core.Modifier, androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRef();
+    method public androidx.ui.layout.ConstraintLayoutScope.ConstrainedLayoutReferences createRefs();
   }
 
-  public final class ConstraintSetBuilderScope {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
+  public final class ConstraintLayoutScope.ConstrainedLayoutReferences {
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component1();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component10();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component11();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component12();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component13();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component14();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component15();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component16();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component2();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component3();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component4();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component5();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component6();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component7();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component8();
+    method public operator androidx.ui.layout.ConstrainedLayoutReference component9();
+  }
+
+  @androidx.compose.Immutable public interface ConstraintSet {
+    method public void applyTo(androidx.ui.layout.State state, java.util.List<? extends androidx.ui.core.Measurable> measurables);
+  }
+
+  @Deprecated public final class ConstraintSetBuilderScope {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createBottomBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromBottom-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromLeft-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor createGuidelineFromRight-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor createGuidelineFromTop-ipo6vVg(float offset);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalChain createHorizontalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createLeftBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor createRightBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor createTopBarrier(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference... elements);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalChain createVerticalChain(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference![] elements, androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle chainStyle = ChainStyle.Spread);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMaxWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getMinWrap(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference getParent();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible getWrap();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWrapFixed();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension max-FmNbr68(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible max-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension min-O_hxsMo(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible min-p2ctyXY(androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible, float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension percent(float percent);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference tag(Object tag);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension.Coercible value-ipo6vVg(float dp);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension valueFixed-ipo6vVg(float dp);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MinCoercible maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension maxWrap;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension.MaxCoercible minWrap;
@@ -119,50 +272,50 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension wrapFixed;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle {
-    field public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
   }
 
-  public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
+  @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed(float bias);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getPacked();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpread();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle getSpreadInside();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Packed;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle Spread;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle SpreadInside;
   }
 
-  public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
-    method public androidx.constraintlayout.core.state.State getState();
-    method public Object getTag();
+  @Deprecated public static final class ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor other);
+    method @Deprecated public androidx.ui.layout.State getState();
+    method @Deprecated public Object getTag();
   }
 
-  public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
-    method public void center();
-    method public void centerHorizontally();
-    method public void centerVertically();
-    method public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
-    method public float getHorizontalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
-    method public Object getTag();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
-    method public float getVerticalBias();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
-    method public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
-    method public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
-    method public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
-    method public void setHorizontalBias(float value);
-    method public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
-    method public void setVerticalBias(float value);
-    method public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+  @Deprecated public final class ConstraintSetBuilderScope.ConstrainedLayoutReference {
+    method @Deprecated public void center();
+    method @Deprecated public void centerHorizontally();
+    method @Deprecated public void centerVertically();
+    method @Deprecated public infix void constrainHorizontallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public infix void constrainVerticallyTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor getBaseline();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getHeight();
+    method @Deprecated public float getHorizontalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+    method @Deprecated public Object getTag();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+    method @Deprecated public float getVerticalBias();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.Dimension getWidth();
+    method @Deprecated public void setBaseline(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor p);
+    method @Deprecated public void setBottom(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setHeight(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
+    method @Deprecated public void setHorizontalBias(float value);
+    method @Deprecated public void setRight(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor p);
+    method @Deprecated public void setVerticalBias(float value);
+    method @Deprecated public void setWidth(androidx.ui.layout.ConstraintSetBuilderScope.Dimension value);
     property public final androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutBaselineAnchor baseline;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension height;
@@ -174,93 +327,98 @@
     property public final androidx.ui.layout.ConstraintSetBuilderScope.Dimension width;
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.Coercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MaxCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
+  @Deprecated public static interface ConstraintSetBuilderScope.Dimension.MinCoercible extends androidx.ui.layout.ConstraintSetBuilderScope.Dimension {
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.HorizontalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.HorizontalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
+  @Deprecated public static final class ConstraintSetBuilderScope.HorizontalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getLeft();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor getRight();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor left;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor right;
   }
 
-  public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
+  @Deprecated public abstract static sealed class ConstraintSetBuilderScope.VerticalAnchor {
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.BarrierAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
-    method public int getIndex$lintWithKotlin();
-    method public float getMargin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
-    method public void setMargin-ipo6vVg(float value);
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.ConstrainedLayoutAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor other);
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public float getMargin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
+    method @Deprecated public void setMargin-ipo6vVg(float value);
     property public final float margin;
     property public Object tag;
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
-    method public int getIndex$lintWithKotlin();
-    method public androidx.constraintlayout.core.state.State getState$lintWithKotlin();
-    method public Object getTag$lintWithKotlin();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalAnchor.GuidelineAnchor extends androidx.ui.layout.ConstraintSetBuilderScope.VerticalAnchor {
+    method @Deprecated public int getIndex$lintWithKotlin();
+    method @Deprecated public androidx.ui.layout.State getState$lintWithKotlin();
+    method @Deprecated public Object getTag$lintWithKotlin();
   }
 
-  public static final class ConstraintSetBuilderScope.VerticalChain {
-    method public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
-    method public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
+  @Deprecated public static final class ConstraintSetBuilderScope.VerticalChain {
+    method @Deprecated public infix void constrainTo(androidx.ui.layout.ConstraintSetBuilderScope.ConstrainedLayoutReference other);
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getBottom();
+    method @Deprecated public androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor getTop();
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor bottom;
     property public final androidx.ui.layout.ConstraintSetBuilderScope.HorizontalAnchor.ConstrainedLayoutAnchor top;
   }
 
-  @androidx.compose.Immutable public final class CrossAxisAlignment {
+  @androidx.ui.layout.LayoutScopeMarker public final class ConstraintSetScope extends androidx.ui.layout.ConstraintLayoutBaseScope {
+    method public androidx.ui.layout.ConstrainScope constrain(androidx.ui.layout.ConstrainedLayoutReference ref, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ConstrainScope,kotlin.Unit> constrainBlock);
+    method public androidx.ui.layout.ConstrainedLayoutReference createRefFor(Object tag);
+  }
+
+  @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
     field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
   }
 
@@ -274,6 +432,31 @@
     property public final androidx.ui.layout.CrossAxisAlignment Start;
   }
 
+  public interface Dimension {
+    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+  }
+
+  public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static final class Dimension.Companion {
+    method public androidx.ui.layout.Dimension getFillToConstraints();
+    method public androidx.ui.layout.Dimension.Coercible getPreferredWrapContent();
+    method public androidx.ui.layout.Dimension getWrapContent();
+    method public androidx.ui.layout.Dimension percent(float percent);
+    method public androidx.ui.layout.Dimension.Coercible preferredValue-ipo6vVg(float dp);
+    method public androidx.ui.layout.Dimension value-ipo6vVg(float dp);
+    property public final androidx.ui.layout.Dimension fillToConstraints;
+    property public final androidx.ui.layout.Dimension.Coercible preferredWrapContent;
+    property public final androidx.ui.layout.Dimension wrapContent;
+  }
+
+  public static interface Dimension.MaxCoercible extends androidx.ui.layout.Dimension {
+  }
+
+  public static interface Dimension.MinCoercible extends androidx.ui.layout.Dimension {
+  }
+
   @androidx.compose.Immutable public final class DpConstraints {
     method public float component1();
     method public float component2();
@@ -440,5 +623,18 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier matchParentSize(androidx.ui.core.Modifier);
   }
 
+  public final class State extends androidx.constraintlayout.core.state.State {
+    ctor public State(androidx.ui.unit.Density density);
+    method public androidx.ui.unit.Density getDensity();
+    method public androidx.ui.core.LayoutDirection getLayoutDirection();
+    method public androidx.ui.core.Constraints getRootIncomingConstraints();
+    method public void setLayoutDirection(androidx.ui.core.LayoutDirection p);
+    method public void setRootIncomingConstraints(androidx.ui.core.Constraints p);
+    property public final androidx.ui.core.LayoutDirection layoutDirection;
+    property public final androidx.ui.core.Constraints rootIncomingConstraints;
+    field public androidx.ui.core.LayoutDirection layoutDirection;
+    field public androidx.ui.core.Constraints rootIncomingConstraints;
+  }
+
 }
 
diff --git a/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutDemo.kt b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutDemo.kt
index b22fecf..02dc4e4 100644
--- a/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutDemo.kt
+++ b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/ConstraintLayoutDemo.kt
@@ -17,128 +17,22 @@
 package androidx.ui.layout.demos
 
 import androidx.compose.Composable
-import androidx.ui.core.Modifier
-import androidx.ui.core.tag
-import androidx.ui.foundation.Box
-import androidx.ui.foundation.Text
-import androidx.ui.foundation.drawBackground
-import androidx.ui.graphics.Color
-import androidx.ui.layout.ConstraintLayout
-import androidx.ui.layout.ConstraintSet
-import androidx.ui.layout.ExperimentalLayout
-import androidx.ui.layout.fillMaxHeight
-import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.preferredSize
-import androidx.ui.layout.preferredWidth
-import androidx.ui.unit.dp
 
 /**
  * Simple ConstraintLayout demo
  */
 @Composable
 fun ConstraintLayoutDemo() {
-//    Demo1()
-//    Demo2()
-    Demo3()
+//    DemoInlineDSL()
+    DemoConstraintSet()
 }
 
 @Composable
-@OptIn(ExperimentalLayout::class)
-fun Demo1() {
-    ConstraintLayout(
-        modifier = Modifier.drawBackground(color = Color.Gray),
-        constraintSet = ConstraintSet {
-            val text1 = tag("text1")
-            val text2 = tag("text2")
-            val divider = tag("divider")
-
-            text1.left constrainTo divider.right
-            text1.right constrainTo parent.right
-            text1.bottom constrainTo parent.bottom
-            text1.top constrainTo parent.top
-            divider.top constrainTo parent.top
-            divider.bottom constrainTo parent.bottom
-            divider.left constrainTo parent.left
-            divider.right constrainTo parent.right
-            text2.top constrainTo divider.top
-            text2.bottom constrainTo divider.bottom
-            text2.verticalBias = 0.2f
-
-            text1.width = wrap
-            text1.height = wrapFixed
-            divider.width = valueFixed(1.dp)
-            divider.height = spread
-        }) {
-        Text(
-            (0 until 100).fold("") { text, value -> "$text$value " },
-            Modifier.tag("text1")
-        )
-        Text("Short text", Modifier.tag("text2"))
-        Box(
-            modifier = Modifier.tag("divider").preferredWidth(1.dp).fillMaxHeight(),
-            backgroundColor = Color.Green
-        )
-    }
+fun DemoInlineDSL() {
+    androidx.ui.layout.samples.DemoInlineDSL()
 }
 
 @Composable
-@OptIn(ExperimentalLayout::class)
-fun Demo2() {
-    ConstraintLayout(
-        modifier = Modifier.drawBackground(Color.Cyan),
-        constraintSet = ConstraintSet {
-            val text = tag("text")
-            val divider = tag("divider")
-            val guideline = createGuidelineFromLeft(0.5f)
-
-            text.left constrainTo guideline
-            text.right constrainTo parent.right
-            text.bottom constrainTo parent.bottom
-            text.top constrainTo parent.top
-            divider.top constrainTo parent.top
-            divider.bottom constrainTo parent.bottom
-            divider.left constrainTo parent.left
-            divider.right constrainTo parent.right
-            divider.width = valueFixed(1.dp)
-            divider.height = spread
-        }) {
-        Text("Short text", Modifier.tag("text"))
-        Box(
-            modifier = Modifier.tag("divider").preferredWidth(1.dp).fillMaxHeight(),
-            backgroundColor = Color.Green
-        )
-    }
-}
-
-@Composable
-@OptIn(ExperimentalLayout::class)
-fun Demo3() {
-    ConstraintLayout(
-        modifier = Modifier.fillMaxSize(),
-        constraintSet = ConstraintSet {
-            val box1 = tag("box1")
-            val box2 = tag("box2")
-            val box3 = tag("box3")
-
-            box1.center()
-
-            val half = createGuidelineFromLeft(percent = 0.5f)
-            box2.apply {
-                left constrainTo half
-                left.margin = 150.dp
-                bottom constrainTo box1.top
-            }
-
-            box3.apply {
-                left constrainTo parent.left
-                left.margin = 150.dp
-                bottom constrainTo parent.bottom
-                bottom.margin = 150.dp
-            }
-        }
-    ) {
-        for (i in 0 until 3) {
-            Box(Modifier.tag("box$i").preferredSize(100.dp, 100.dp), backgroundColor = Color.Blue)
-        }
-    }
+fun DemoConstraintSet() {
+    androidx.ui.layout.samples.DemoConstraintSet()
 }
\ No newline at end of file
diff --git a/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/LayoutDemos.kt b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/LayoutDemos.kt
index 420f585..10554b7 100644
--- a/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/LayoutDemos.kt
+++ b/ui/ui-layout/integration-tests/layout-demos/src/main/java/androidx/ui/layout/demos/LayoutDemos.kt
@@ -22,7 +22,10 @@
 
 val LayoutDemos = DemoCategory("Layout", listOf(
     ComposableDemo("Complex layout") { ComplexLayoutDemo() },
-    ComposableDemo("ConstraintLayout") { ConstraintLayoutDemo() },
+    DemoCategory("ConstraintLayout", listOf(
+        ComposableDemo("With inline (modifier based) DSL") { DemoInlineDSL() },
+        ComposableDemo("With ConstraintSet DSL") { DemoConstraintSet() }
+    )),
     ComposableDemo("Flow layout") { SimpleFlowRow() },
     ComposableDemo("Row and column") { SimpleLayoutDemo() },
     ComposableDemo("Rtl support") { RtlDemo() }
diff --git a/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/ConstraintLayoutSample.kt b/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/ConstraintLayoutSample.kt
new file mode 100644
index 0000000..e68eee8
--- /dev/null
+++ b/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/ConstraintLayoutSample.kt
@@ -0,0 +1,78 @@
+/*
+ * 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.layout.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.Composable
+import androidx.ui.core.Modifier
+import androidx.ui.core.tag
+import androidx.ui.foundation.Text
+import androidx.ui.layout.ConstraintLayout
+import androidx.ui.layout.ConstraintSet2
+import androidx.ui.layout.Dimension
+import androidx.ui.layout.atMost
+import androidx.ui.unit.dp
+
+@Sampled
+@Composable
+fun DemoInlineDSL() {
+    ConstraintLayout {
+        val (text1, text2, text3) = createRefs()
+
+        Text("Text1", Modifier.constrainAs(text1) {
+            start.linkTo(text2.end, margin = 20.dp)
+        })
+        Text("Text2", Modifier.constrainAs(text2) {
+            centerTo(parent)
+        })
+
+        val barrier = createBottomBarrier(text1, text2)
+        Text("This is a very long text", Modifier.constrainAs(text3) {
+            top.linkTo(barrier, margin = 20.dp)
+            centerHorizontallyTo(parent)
+            width = Dimension.preferredWrapContent.atMost(40.dp)
+        })
+    }
+}
+
+@Sampled
+@Composable
+fun DemoConstraintSet() {
+    ConstraintLayout(ConstraintSet2 {
+        val text1 = createRefFor("text1")
+        val text2 = createRefFor("text2")
+        val text3 = createRefFor("text3")
+
+        constrain(text1) {
+            start.linkTo(text2.end, margin = 20.dp)
+        }
+        constrain(text2) {
+            centerTo(parent)
+        }
+
+        val barrier = createBottomBarrier(text1, text2)
+        constrain(text3) {
+            top.linkTo(barrier, margin = 20.dp)
+            centerHorizontallyTo(parent)
+            width = Dimension.preferredWrapContent.atMost(40.dp)
+        }
+    }) {
+        Text("Text1", Modifier.tag("text1"))
+        Text("Text2", Modifier.tag("text2"))
+        Text("This is a very long text", Modifier.tag("text3"))
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/SizeModifierSample.kt b/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/SizeModifierSample.kt
index 8bc1645..ec53828 100644
--- a/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/SizeModifierSample.kt
+++ b/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/SizeModifierSample.kt
@@ -197,10 +197,10 @@
             backgroundColor = Color.Blue
         )
     }
-    // This will be a 10.dp x 10.dp blue box. Because we are not providing any min constraints
+    // This will be a 100.dp x 100.dp blue box. Because we are not providing any min constraints
     // to the DefaultMinBox, defaultMinSizeConstraints will apply its min constraints.
     DefaultMinBox()
-    // This will be a 5.dp x 5.dp blue box. Because we are providing min constraints
+    // This will be a 50.dp x 50.dp blue box. Because we are providing min constraints
     // to the DefaultMinBox, defaultMinSizeConstraints will not apply its min constraints.
     DefaultMinBox(Modifier.sizeIn(minWidth = 50.dp, minHeight = 50.dp))
     // Note that if DefaultMinBox used sizeIn or preferredSizeIn rather than
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignmentLineTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignmentLineTest.kt
index f2fddbc..2b81664 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignmentLineTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/AlignmentLineTest.kt
@@ -25,16 +25,14 @@
 import androidx.ui.core.WithConstraints
 import androidx.ui.core.globalPosition
 import androidx.ui.core.onPositioned
+import androidx.ui.geometry.Offset
 import androidx.ui.layout.Stack
 import androidx.ui.layout.preferredSizeIn
 import androidx.ui.layout.relativePaddingFrom
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.min
-import androidx.ui.unit.px
-import androidx.ui.unit.toPx
 import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -49,14 +47,14 @@
     fun testRelativePaddingFrom_vertical() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = VerticalAlignmentLine(::min)
-        val beforeDp = 20.px.toDp()
-        val afterDp = 40.px.toDp()
-        val childDp = 30.px.toDp()
-        val lineDp = 10.px.toDp()
+        val beforeDp = 20f.toDp()
+        val afterDp = 40f.toDp()
+        val childDp = 30f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(
                 Modifier.onPositioned {
@@ -88,7 +86,7 @@
         Assert.assertEquals(childSize.value!!.height, parentSize.value!!.height)
         Assert.assertNotNull(childPosition.value)
         Assert.assertEquals(
-            (beforeDp.toIntPx().toPx() - lineDp.toIntPx().toPx()).value,
+            (beforeDp.toIntPx().value - lineDp.toIntPx().value).toFloat(),
             childPosition.value!!.x
         )
         Assert.assertEquals(0f, childPosition.value!!.y)
@@ -98,14 +96,14 @@
     fun testRelativePaddingFrom_horizontal() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = HorizontalAlignmentLine(::min)
-        val beforeDp = 20.px.toDp()
-        val afterDp = 40.px.toDp()
-        val childDp = 30.px.toDp()
-        val lineDp = 10.px.toDp()
+        val beforeDp = 20f.toDp()
+        val afterDp = 40f.toDp()
+        val childDp = 30f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(
                 modifier = Modifier.onPositioned {
@@ -136,7 +134,7 @@
         Assert.assertNotNull(childPosition.value)
         Assert.assertEquals(0f, childPosition.value!!.x)
         Assert.assertEquals(
-            (beforeDp.toIntPx().toPx() - lineDp.toIntPx().toPx()).value,
+            (beforeDp.toIntPx().value - lineDp.toIntPx().value).toFloat(),
             childPosition.value!!.y
         )
     }
@@ -145,14 +143,14 @@
     fun testRelativePaddingFrom_vertical_withSmallOffsets() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = VerticalAlignmentLine(::min)
-        val beforeDp = 5.px.toDp()
-        val afterDp = 5.px.toDp()
-        val childDp = 30.px.toDp()
-        val lineDp = 10.px.toDp()
+        val beforeDp = 5f.toDp()
+        val afterDp = 5f.toDp()
+        val childDp = 30f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.saveLayoutInfo(parentSize, Ref(), layoutLatch)) {
                 Layout(
@@ -179,14 +177,14 @@
     fun testRelativePaddingFrom_horizontal_withSmallOffsets() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = HorizontalAlignmentLine(::min)
-        val beforeDp = 5.px.toDp()
-        val afterDp = 5.px.toDp()
-        val childDp = 30.px.toDp()
-        val lineDp = 10.px.toDp()
+        val beforeDp = 5f.toDp()
+        val afterDp = 5f.toDp()
+        val childDp = 30f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(Modifier.saveLayoutInfo(parentSize, Ref(), layoutLatch)) {
                 Layout(
@@ -213,15 +211,15 @@
     fun testRelativePaddingFrom_vertical_withInsufficientSpace() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = VerticalAlignmentLine(::min)
-        val maxWidth = 30.px.toDp()
-        val beforeDp = 20.px.toDp()
-        val afterDp = 20.px.toDp()
-        val childDp = 25.px.toDp()
-        val lineDp = 10.px.toDp()
+        val maxWidth = 30f.toDp()
+        val beforeDp = 20f.toDp()
+        val afterDp = 20f.toDp()
+        val childDp = 25f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(Modifier.saveLayoutInfo(parentSize, Ref(), layoutLatch)) {
                 Layout(
@@ -254,15 +252,15 @@
     fun testRelativePaddingFrom_horizontal_withInsufficientSpace() = with(density) {
         val layoutLatch = CountDownLatch(2)
         val testLine = HorizontalAlignmentLine(::min)
-        val maxHeight = 30.px.toDp()
-        val beforeDp = 20.px.toDp()
-        val afterDp = 20.px.toDp()
-        val childDp = 25.px.toDp()
-        val lineDp = 10.px.toDp()
+        val maxHeight = 30f.toDp()
+        val beforeDp = 20f.toDp()
+        val afterDp = 20f.toDp()
+        val childDp = 25f.toDp()
+        val lineDp = 10f.toDp()
 
         val parentSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(Modifier.saveLayoutInfo(parentSize, Ref(), layoutLatch)) {
                 Layout(
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ConstraintLayoutTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ConstraintLayoutTest.kt
index 5b49701..324a8eb 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ConstraintLayoutTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ConstraintLayoutTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.layout.test
 
+import androidx.compose.mutableStateOf
 import androidx.test.filters.SmallTest
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
@@ -23,9 +24,12 @@
 import androidx.ui.core.tag
 import androidx.ui.core.globalPosition
 import androidx.ui.core.onPositioned
+import androidx.ui.core.positionInParent
 import androidx.ui.foundation.Box
+import androidx.ui.layout.ConstrainScope
 import androidx.ui.layout.ConstraintLayout
-import androidx.ui.layout.ConstraintSet
+import androidx.ui.layout.ConstraintSet2
+import androidx.ui.layout.Dimension
 import androidx.ui.layout.ExperimentalLayout
 import androidx.ui.layout.aspectRatio
 import androidx.ui.layout.fillMaxSize
@@ -33,13 +37,16 @@
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.preferredWidth
 import androidx.ui.layout.rtl
+import androidx.ui.layout.size
 import androidx.ui.layout.wrapContentSize
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.runOnIdleCompose
+import androidx.ui.test.waitForIdle
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
+import org.junit.Assert
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -61,23 +68,18 @@
         composeTestRule.setContent {
             ConstraintLayout(
                 // Make CL fixed width and wrap content height.
-                modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth(),
-                constraintSet = ConstraintSet {
-                    val aspectRatioBox = tag("aspectRatioBox")
-                    val divider = tag("divider")
-                    val guideline = createGuidelineFromLeft(0.5f)
-
-                    aspectRatioBox constrainTo parent
-                    aspectRatioBox.left constrainTo guideline
-                    divider constrainTo parent
-
-                    aspectRatioBox.width = wrap
-                    aspectRatioBox.height = wrapFixed
-                    divider.width = valueFixed(1.dp)
-                    divider.height = spread
-                }
+                modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth()
             ) {
-                Box(Modifier.tag("aspectRatioBox")
+                val (aspectRatioBox, divider) = createRefs()
+                val guideline = createGuidelineFromAbsoluteLeft(0.5f)
+
+                Box(Modifier
+                    .constrainAs(aspectRatioBox) {
+                        centerTo(parent)
+                        start.linkTo(guideline)
+                        width = Dimension.preferredWrapContent
+                        height = Dimension.wrapContent
+                    }
                     // Try to be large to make wrap content impossible.
                     .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
                     // This could be any (width in height out child) e.g. text
@@ -86,8 +88,12 @@
                         aspectRatioBoxSize.value = coordinates.size
                     }
                 )
-                Box(Modifier.tag("divider")
-                    .onPositioned { coordinates ->
+                Box(Modifier
+                    .constrainAs(divider) {
+                        centerTo(parent)
+                        width = Dimension.value(1.dp)
+                        height = Dimension.fillToConstraints
+                    }.onPositioned { coordinates ->
                         dividerSize.value = coordinates.size
                     }
                 )
@@ -120,23 +126,18 @@
         composeTestRule.setContent {
             ConstraintLayout(
                 // Make CL fixed width and wrap content height.
-                modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth(),
-                constraintSet = ConstraintSet {
-                    val aspectRatioBox = tag("aspectRatioBox")
-                    val divider = tag("divider")
-                    val guideline = createGuidelineFromLeft(0.5f)
-
-                    aspectRatioBox constrainTo parent
-                    aspectRatioBox.left constrainTo guideline
-                    divider constrainTo parent
-
-                    aspectRatioBox.width = wrap
-                    aspectRatioBox.height = wrapFixed
-                    divider.width = valueFixed(1.dp)
-                    divider.height = percent(0.8f)
-                }
+                modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth()
             ) {
-                Box(Modifier.tag("aspectRatioBox")
+                val (aspectRatioBox, divider) = createRefs()
+                val guideline = createGuidelineFromAbsoluteLeft(0.5f)
+
+                Box(Modifier
+                    .constrainAs(aspectRatioBox) {
+                        centerTo(parent)
+                        start.linkTo(guideline)
+                        width = Dimension.preferredWrapContent
+                        height = Dimension.wrapContent
+                    }
                     // Try to be large to make wrap content impossible.
                     .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
                     // This could be any (width in height out child) e.g. text
@@ -145,7 +146,12 @@
                         aspectRatioBoxSize.value = coordinates.size
                     }
                 )
-                Box(Modifier.tag("divider")
+                Box(Modifier
+                    .constrainAs(divider) {
+                        centerTo(parent)
+                        width = Dimension.value(1.dp)
+                        height = Dimension.percent(0.8f)
+                    }
                     .onPositioned { coordinates ->
                         dividerSize.value = coordinates.size
                     }
@@ -168,7 +174,6 @@
             assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
             // Divider has percent height so it should spread to fill 0.8 of the height of the CL,
             // which in turns is given by the size of the aspect ratio box.
-            // TODO(popam; b/150277566): uncomment
             assertEquals(aspectRatioBoxSize.value!!.height * 0.8f, dividerSize.value!!.height)
         }
     }
@@ -180,23 +185,18 @@
         composeTestRule.setContent {
             ConstraintLayout(
                 // Make CL wrap width and height.
-                modifier = Modifier.wrapContentSize(Alignment.TopStart),
-                constraintSet = ConstraintSet {
-                    val aspectRatioBox = tag("aspectRatioBox")
-                    val divider = tag("divider")
-                    val guideline = createGuidelineFromLeft(0.5f)
-
-                    aspectRatioBox constrainTo parent
-                    aspectRatioBox.left constrainTo guideline
-                    divider constrainTo parent
-
-                    aspectRatioBox.width = wrap
-                    aspectRatioBox.height = wrapFixed
-                    divider.width = valueFixed(1.dp)
-                    divider.height = percent(0.8f)
-                }
+                modifier = Modifier.wrapContentSize(Alignment.TopStart)
             ) {
-                Box(Modifier.tag("aspectRatioBox")
+                val (aspectRatioBox, divider) = createRefs()
+                val guideline = createGuidelineFromAbsoluteLeft(0.5f)
+
+                Box(Modifier
+                    .constrainAs(aspectRatioBox) {
+                        centerTo(parent)
+                        start.linkTo(guideline)
+                        width = Dimension.preferredWrapContent
+                        height = Dimension.wrapContent
+                    }
                     // Try to be large to make wrap content impossible.
                     .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
                     // This could be any (width in height out child) e.g. text
@@ -205,7 +205,12 @@
                         aspectRatioBoxSize.value = coordinates.size
                     }
                 )
-                Box(Modifier.tag("divider")
+                Box(Modifier
+                    .constrainAs(divider) {
+                        centerTo(parent)
+                        width = Dimension.value(1.dp)
+                        height = Dimension.percent(0.8f)
+                    }
                     .onPositioned { coordinates ->
                         dividerSize.value = coordinates.size
                     }
@@ -244,32 +249,32 @@
                 // Make CL wrap width and height.
                 modifier = Modifier.wrapContentSize(Alignment.TopStart).onPositioned {
                     constraintLayoutSize.value = it.size
-                },
-                constraintSet = ConstraintSet {
-                    val aspectRatioBox = tag("aspectRatioBox")
-                    val divider = tag("divider")
-                    val guideline = createGuidelineFromLeft(0.5f)
-
-                    aspectRatioBox constrainTo parent
-                    aspectRatioBox.left constrainTo guideline
-                    divider constrainTo parent
-
-                    aspectRatioBox.width = wrap
-                    aspectRatioBox.height = wrapFixed
-                    divider.width = valueFixed(1.dp)
-                    divider.height = spread
                 }
             ) {
-                Box(Modifier.tag("aspectRatioBox")
-                        // Small width for the CL to wrap it.
+                val (aspectRatioBox, divider) = createRefs()
+                val guideline = createGuidelineFromAbsoluteLeft(0.5f)
+
+                Box(Modifier
+                    .constrainAs(aspectRatioBox) {
+                        centerTo(parent)
+                        start.linkTo(guideline)
+                        width = Dimension.preferredWrapContent
+                        height = Dimension.wrapContent
+                    }
+                    // Small width for the CL to wrap it.
                     .preferredWidth(size)
-                        // This could be any (width in height out child) e.g. text
+                    // This could be any (width in height out child) e.g. text
                     .aspectRatio(2f)
                     .onPositioned { coordinates ->
                         aspectRatioBoxSize.value = coordinates.size
                     }
                 )
-                Box(Modifier.tag("divider")
+                Box(Modifier
+                    .constrainAs(divider) {
+                        centerTo(parent)
+                        width = Dimension.value(1.dp)
+                        height = Dimension.fillToConstraints
+                    }
                     .onPositioned { coordinates ->
                         dividerSize.value = coordinates.size
                     }
@@ -298,32 +303,102 @@
     // region positioning tests
 
     @Test
-    fun testConstraintLayout() = with(density) {
+    fun testConstraintLayout_withInlineDSL() = with(density) {
         val boxSize = 100.ipx
         val offset = 150.ipx
 
-        val position = Array(3) { Ref<PxPosition>() }
+        val position = Array(3) { Ref<Offset>() }
 
         composeTestRule.setContent {
-            ConstraintLayout(ConstraintSet {
-                    val box0 = tag("box0")
-                    val box1 = tag("box1")
-                    val box2 = tag("box2")
+            ConstraintLayout(Modifier.fillMaxSize()) {
+                val (box0, box1, box2) = createRefs()
+                Box(Modifier
+                    .constrainAs(box0) {
+                        centerTo(parent)
+                    }
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[0].value = it.globalPosition
+                    }
+                )
+                val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
+                Box(Modifier
+                    .constrainAs(box1) {
+                        start.linkTo(half, margin = offset.toDp())
+                        bottom.linkTo(box0.top)
+                    }
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[1].value = it.globalPosition
+                    }
+                )
+                Box(Modifier
+                    .constrainAs(box2) {
+                        start.linkTo(parent.start, margin = offset.toDp())
+                        bottom.linkTo(parent.bottom, margin = offset.toDp())
+                    }
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[2].value = it.globalPosition
+                    }
+                )
+            }
+        }
 
-                    box0.center()
+        val displayWidth = composeTestRule.displayMetrics.widthPixels.ipx
+        val displayHeight = composeTestRule.displayMetrics.heightPixels.ipx
 
-                    val half = createGuidelineFromLeft(percent = 0.5f)
-                    box1.apply {
-                        left constrainTo half
-                        left.margin = offset.toDp()
-                        bottom constrainTo box0.top
+        runOnIdleCompose {
+            assertEquals(
+                Offset(
+                    ((displayWidth - boxSize) / 2).value.toFloat(),
+                    ((displayHeight - boxSize) / 2).value.toFloat()),
+                position[0].value
+            )
+            assertEquals(
+                Offset(
+                    (displayWidth / 2 + offset).value.toFloat(),
+                    ((displayHeight - boxSize) / 2 - boxSize).value.toFloat()
+                ),
+                position[1].value
+            )
+            assertEquals(
+                Offset(
+                    offset.value.toFloat(),
+                    (displayHeight - boxSize - offset).value.toFloat()
+                ),
+                position[2].value
+            )
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_withConstraintSet() = with(density) {
+        val boxSize = 100.ipx
+        val offset = 150.ipx
+
+        val position = Array(3) { Ref<Offset>() }
+
+        composeTestRule.setContent {
+            ConstraintLayout(
+                ConstraintSet2 {
+                    val box0 = createRefFor("box0")
+                    val box1 = createRefFor("box1")
+                    val box2 = createRefFor("box2")
+
+                    constrain(box0) {
+                        centerTo(parent)
                     }
 
-                    box2.apply {
-                        left constrainTo parent.left
-                        left.margin = offset.toDp()
-                        bottom constrainTo parent.bottom
-                        bottom.margin = offset.toDp()
+                    val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
+                    constrain(box1) {
+                        start.linkTo(half, margin = offset.toDp())
+                        bottom.linkTo(box0.top)
+                    }
+
+                    constrain(box2) {
+                        start.linkTo(parent.start, margin = offset.toDp())
+                        bottom.linkTo(parent.bottom, margin = offset.toDp())
                     }
                 },
                 Modifier.fillMaxSize()
@@ -343,15 +418,24 @@
 
         runOnIdleCompose {
             assertEquals(
-                PxPosition((displayWidth - boxSize) / 2, (displayHeight - boxSize) / 2),
+                Offset(
+                    (displayWidth - boxSize).value / 2f,
+                    (displayHeight - boxSize).value / 2f
+                ),
                 position[0].value
             )
             assertEquals(
-                PxPosition(displayWidth / 2 + offset, (displayHeight - boxSize) / 2 - boxSize),
+                Offset(
+                    (displayWidth / 2f + offset).value.toFloat(),
+                    ((displayHeight - boxSize) / 2 - boxSize).value.toFloat()
+                ),
                 position[1].value
             )
             assertEquals(
-                PxPosition(offset, displayHeight - boxSize - offset),
+                Offset(
+                    offset.value.toFloat(),
+                    (displayHeight - boxSize - offset).value.toFloat()
+                ),
                 position[2].value
             )
         }
@@ -362,40 +446,41 @@
         val boxSize = 100.ipx
         val offset = 150.ipx
 
-        val position = Array(3) { Ref<PxPosition>() }
+        val position = Array(3) { Ref<Offset>() }
 
         composeTestRule.setContent {
-            ConstraintLayout(
-                modifier = Modifier.rtl.fillMaxSize(),
-                constraintSet = ConstraintSet {
-                    val box0 = tag("box0")
-                    val box1 = tag("box1")
-                    val box2 = tag("box2")
-
-                    box0.center()
-
-                    val half = createGuidelineFromLeft(percent = 0.5f)
-                    box1.apply {
-                        left constrainTo half
-                        left.margin = offset.toDp()
-                        bottom constrainTo box0.top
+            ConstraintLayout(Modifier.rtl.fillMaxSize()) {
+                val (box0, box1, box2) = createRefs()
+                Box(Modifier
+                    .constrainAs(box0) {
+                        centerTo(parent)
                     }
-
-                    box2.apply {
-                        left constrainTo parent.left
-                        left.margin = offset.toDp()
-                        bottom constrainTo parent.bottom
-                        bottom.margin = offset.toDp()
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[0].value = it.globalPosition
                     }
-                }
-            ) {
-                for (i in 0..2) {
-                    Box(Modifier.tag("box$i").preferredSize(boxSize.toDp(), boxSize.toDp())
-                        .onPositioned {
-                            position[i].value = it.globalPosition
-                        }
-                    )
-                }
+                )
+                val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
+                Box(Modifier
+                    .constrainAs(box1) {
+                        start.linkTo(half, margin = offset.toDp())
+                        bottom.linkTo(box0.top)
+                    }
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[1].value = it.globalPosition
+                    }
+                )
+                Box(Modifier
+                    .constrainAs(box2) {
+                        start.linkTo(parent.start, margin = offset.toDp())
+                        bottom.linkTo(parent.bottom, margin = offset.toDp())
+                    }
+                    .preferredSize(boxSize.toDp(), boxSize.toDp())
+                    .onPositioned {
+                        position[2].value = it.globalPosition
+                    }
+                )
             }
         }
 
@@ -404,20 +489,439 @@
 
         runOnIdleCompose {
             assertEquals(
-                PxPosition((displayWidth - boxSize) / 2, (displayHeight - boxSize) / 2),
+                Offset(
+                    (displayWidth - boxSize).value / 2f,
+                    (displayHeight - boxSize).value / 2f
+                ),
                 position[0].value
             )
             assertEquals(
-                PxPosition(
-                    displayWidth / 2 - offset - boxSize,
-                    (displayHeight - boxSize) / 2 - boxSize
+                Offset(
+                    (displayWidth / 2 - offset - boxSize).value.toFloat(),
+                    ((displayHeight - boxSize) / 2 - boxSize).value.toFloat()
                 ),
                 position[1].value
             )
             assertEquals(
-                PxPosition(displayWidth - offset - boxSize, displayHeight - boxSize - offset),
+                Offset(
+                    (displayWidth - offset - boxSize).value.toFloat(),
+                    (displayHeight - boxSize - offset).value.toFloat()
+                ),
                 position[2].value
             )
         }
     }
+
+    @Test
+    fun testConstraintLayout_helpers_ltr() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(8) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size)) {
+                val guidelines = arrayOf(
+                    createGuidelineFromStart(offset),
+                    createGuidelineFromAbsoluteLeft(offset),
+                    createGuidelineFromEnd(offset),
+                    createGuidelineFromAbsoluteRight(offset),
+                    createGuidelineFromStart(0.25f),
+                    createGuidelineFromAbsoluteLeft(0.25f),
+                    createGuidelineFromEnd(0.25f),
+                    createGuidelineFromAbsoluteRight(0.25f)
+                )
+
+                guidelines.forEachIndexed { index, guideline ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.dp)
+                        .constrainAs(ref) {
+                            absoluteLeft.linkTo(guideline)
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(50f, position[0])
+            Assert.assertEquals(50f, position[1])
+            Assert.assertEquals(150f, position[2])
+            Assert.assertEquals(150f, position[3])
+            Assert.assertEquals(50f, position[4])
+            Assert.assertEquals(50f, position[5])
+            Assert.assertEquals(150f, position[6])
+            Assert.assertEquals(150f, position[7])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_helpers_rtl() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(8) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size).rtl) {
+                val guidelines = arrayOf(
+                    createGuidelineFromStart(offset),
+                    createGuidelineFromAbsoluteLeft(offset),
+                    createGuidelineFromEnd(offset),
+                    createGuidelineFromAbsoluteRight(offset),
+                    createGuidelineFromStart(0.25f),
+                    createGuidelineFromAbsoluteLeft(0.25f),
+                    createGuidelineFromEnd(0.25f),
+                    createGuidelineFromAbsoluteRight(0.25f)
+                )
+
+                guidelines.forEachIndexed { index, guideline ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.dp)
+                        .constrainAs(ref) {
+                            absoluteLeft.linkTo(guideline)
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(150f, position[0])
+            Assert.assertEquals(50f, position[1])
+            Assert.assertEquals(50f, position[2])
+            Assert.assertEquals(150f, position[3])
+            Assert.assertEquals(150f, position[4])
+            Assert.assertEquals(50f, position[5])
+            Assert.assertEquals(50f, position[6])
+            Assert.assertEquals(150f, position[7])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_barriers_ltr() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(4) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size)) {
+                val (box1, box2) = createRefs()
+                val guideline1 = createGuidelineFromAbsoluteLeft(offset)
+                val guideline2 = createGuidelineFromAbsoluteRight(offset)
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box1) {
+                        absoluteLeft.linkTo(guideline1)
+                    }
+                )
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box2) {
+                        absoluteLeft.linkTo(guideline2)
+                    }
+                )
+
+                val barriers = arrayOf(
+                    createStartBarrier(box1, box2),
+                    createAbsoluteLeftBarrier(box1, box2),
+                    createEndBarrier(box1, box2),
+                    createAbsoluteRightBarrier(box1, box2)
+                )
+
+                barriers.forEachIndexed { index, barrier ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.dp)
+                        .constrainAs(ref) {
+                            absoluteLeft.linkTo(barrier)
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(50f, position[0])
+            Assert.assertEquals(50f, position[1])
+            Assert.assertEquals(151f, position[2])
+            Assert.assertEquals(151f, position[3])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_barriers_rtl() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(4) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size).rtl) {
+                val (box1, box2) = createRefs()
+                val guideline1 = createGuidelineFromAbsoluteLeft(offset)
+                val guideline2 = createGuidelineFromAbsoluteRight(offset)
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box1) {
+                        absoluteLeft.linkTo(guideline1)
+                    }
+                )
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box2) {
+                        absoluteLeft.linkTo(guideline2)
+                    }
+                )
+
+                val barriers = arrayOf(
+                    createStartBarrier(box1, box2),
+                    createAbsoluteLeftBarrier(box1, box2),
+                    createEndBarrier(box1, box2),
+                    createAbsoluteRightBarrier(box1, box2)
+                )
+
+                barriers.forEachIndexed { index, barrier ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.dp)
+                        .constrainAs(ref) {
+                            absoluteLeft.linkTo(barrier)
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(151f, position[0])
+            Assert.assertEquals(50f, position[1])
+            Assert.assertEquals(50f, position[2])
+            Assert.assertEquals(151f, position[3])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_anchors_ltr() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(16) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size)) {
+                val box = createRef()
+                val guideline = createGuidelineFromAbsoluteLeft(offset)
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box) {
+                        absoluteLeft.linkTo(guideline)
+                    }
+                )
+
+                val anchors = listOf<ConstrainScope.() -> Unit>(
+                    { start.linkTo(box.start) },
+                    { absoluteLeft.linkTo(box.start) },
+                    { start.linkTo(box.absoluteLeft) },
+                    { absoluteLeft.linkTo(box.absoluteLeft) },
+                    { end.linkTo(box.start) },
+                    { absoluteRight.linkTo(box.start) },
+                    { end.linkTo(box.absoluteLeft) },
+                    { absoluteRight.linkTo(box.absoluteLeft) },
+                    { start.linkTo(box.end) },
+                    { absoluteLeft.linkTo(box.end) },
+                    { start.linkTo(box.absoluteRight) },
+                    { absoluteLeft.linkTo(box.absoluteRight) },
+                    { end.linkTo(box.end) },
+                    { absoluteRight.linkTo(box.end) },
+                    { end.linkTo(box.absoluteRight) },
+                    { absoluteRight.linkTo(box.absoluteRight) }
+                )
+
+                anchors.forEachIndexed { index, anchor ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.ipx.toDp())
+                        .constrainAs(ref) {
+                            anchor()
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(50f, position[0])
+            Assert.assertEquals(50f, position[1])
+            Assert.assertEquals(50f, position[2])
+            Assert.assertEquals(50f, position[3])
+            Assert.assertEquals(49f, position[4])
+            Assert.assertEquals(49f, position[5])
+            Assert.assertEquals(49f, position[6])
+            Assert.assertEquals(49f, position[7])
+            Assert.assertEquals(51f, position[8])
+            Assert.assertEquals(51f, position[9])
+            Assert.assertEquals(51f, position[10])
+            Assert.assertEquals(51f, position[11])
+            Assert.assertEquals(50f, position[12])
+            Assert.assertEquals(50f, position[13])
+            Assert.assertEquals(50f, position[14])
+            Assert.assertEquals(50f, position[15])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_anchors_rtl() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(16) { 0f }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size).rtl) {
+                val box = createRef()
+                val guideline = createGuidelineFromAbsoluteLeft(offset)
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box) {
+                        absoluteLeft.linkTo(guideline)
+                    }
+                )
+
+                val anchors = listOf<ConstrainScope.() -> Unit>(
+                    { start.linkTo(box.start) },
+                    { absoluteLeft.linkTo(box.start) },
+                    { start.linkTo(box.absoluteLeft) },
+                    { absoluteLeft.linkTo(box.absoluteLeft) },
+                    { end.linkTo(box.start) },
+                    { absoluteRight.linkTo(box.start) },
+                    { end.linkTo(box.absoluteLeft) },
+                    { absoluteRight.linkTo(box.absoluteLeft) },
+                    { start.linkTo(box.end) },
+                    { absoluteLeft.linkTo(box.end) },
+                    { start.linkTo(box.absoluteRight) },
+                    { absoluteLeft.linkTo(box.absoluteRight) },
+                    { end.linkTo(box.end) },
+                    { absoluteRight.linkTo(box.end) },
+                    { end.linkTo(box.absoluteRight) },
+                    { absoluteRight.linkTo(box.absoluteRight) }
+                )
+
+                anchors.forEachIndexed { index, anchor ->
+                    val ref = createRef()
+                    Box(Modifier.size(1.ipx.toDp())
+                        .constrainAs(ref) {
+                            anchor()
+                        }.onPositioned {
+                            position[index] = it.positionInParent.x
+                        }
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(50f, position[0])
+            Assert.assertEquals(51f, position[1])
+            Assert.assertEquals(49f, position[2])
+            Assert.assertEquals(50f, position[3])
+            Assert.assertEquals(51f, position[4])
+            Assert.assertEquals(50f, position[5])
+            Assert.assertEquals(50f, position[6])
+            Assert.assertEquals(49f, position[7])
+            Assert.assertEquals(49f, position[8])
+            Assert.assertEquals(50f, position[9])
+            Assert.assertEquals(50f, position[10])
+            Assert.assertEquals(51f, position[11])
+            Assert.assertEquals(50f, position[12])
+            Assert.assertEquals(49f, position[13])
+            Assert.assertEquals(51f, position[14])
+            Assert.assertEquals(50f, position[15])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_barriers_margins() = with(density) {
+        val size = 200.ipx.toDp()
+        val offset = 50.ipx.toDp()
+
+        val position = Array(2) { Offset(0f, 0f) }
+        composeTestRule.setContent {
+            ConstraintLayout(Modifier.size(size)) {
+                val box = createRef()
+                val guideline1 = createGuidelineFromAbsoluteLeft(offset)
+                val guideline2 = createGuidelineFromTop(offset)
+                Box(Modifier.size(1.ipx.toDp())
+                    .constrainAs(box) {
+                        absoluteLeft.linkTo(guideline1)
+                        top.linkTo(guideline2)
+                    }
+                )
+
+                val leftBarrier = createAbsoluteLeftBarrier(box, margin = 10.ipx.toDp())
+                val topBarrier = createTopBarrier(box, margin = 10.ipx.toDp())
+                val rightBarrier = createAbsoluteRightBarrier(box, margin = 10.ipx.toDp())
+                val bottomBarrier = createBottomBarrier(box, margin = 10.ipx.toDp())
+
+                Box(Modifier.size(1.dp)
+                    .constrainAs(createRef()) {
+                        absoluteLeft.linkTo(leftBarrier)
+                        top.linkTo(topBarrier)
+                    }.onPositioned {
+                        position[0] = it.positionInParent
+                    }
+                )
+
+                Box(Modifier.size(1.dp)
+                    .constrainAs(createRef()) {
+                        absoluteLeft.linkTo(rightBarrier)
+                        top.linkTo(bottomBarrier)
+                    }.onPositioned {
+                        position[1] = it.positionInParent
+                    }
+                )
+            }
+        }
+
+        runOnIdleCompose {
+            Assert.assertEquals(Offset(60f, 60f), position[0])
+            Assert.assertEquals(Offset(61f, 61f), position[1])
+        }
+    }
+
+    @Test
+    fun testConstraintLayout_inlineDSL_recompositionDoesNotCrash() = with(density) {
+        val first = mutableStateOf(true)
+        composeTestRule.setContent {
+            ConstraintLayout {
+                val box = createRef()
+                if (first.value) {
+                    Box(Modifier.constrainAs(box) { })
+                } else {
+                    Box(Modifier.constrainAs(box) { })
+                }
+            }
+        }
+        runOnIdleCompose {
+            first.value = false
+        }
+        waitForIdle()
+    }
+
+    @Test
+    fun testConstraintLayout_ConstraintSetDSL_recompositionDoesNotCrash() = with(density) {
+        val first = mutableStateOf(true)
+        composeTestRule.setContent {
+            ConstraintLayout(ConstraintSet2 {
+                val box = createRefFor("box")
+                constrain(box) { }
+            }) {
+                if (first.value) {
+                    Box(Modifier.tag("box"))
+                } else {
+                    Box(Modifier.tag("box"))
+                }
+            }
+        }
+        runOnIdleCompose {
+            first.value = false
+        }
+        waitForIdle()
+    }
 }
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ContainerTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ContainerTest.kt
index 381712a..f9662aa 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ContainerTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/ContainerTest.kt
@@ -34,11 +34,9 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.round
-import androidx.ui.unit.toPx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
@@ -46,6 +44,7 @@
 import org.junit.runners.JUnit4
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
 
 @SmallTest
 @RunWith(JUnit4::class)
@@ -81,7 +80,7 @@
 
         val positionedLatch = CountDownLatch(2)
         val containerSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack {
                 Container(
@@ -93,7 +92,7 @@
                 ) {
                     EmptyBox(width = sizeDp, height = sizeDp,
                         modifier = Modifier.onPositioned { coordinates ->
-                            childPosition.value = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition.value = coordinates.localToGlobal(Offset(0f, 0f))
                             positionedLatch.countDown()
                         }
                     )
@@ -107,7 +106,7 @@
             IntPxSize(size + totalPadding, size + totalPadding),
             containerSize.value
         )
-        assertEquals(PxPosition(padding, padding), childPosition.value)
+        assertEquals(Offset(padding.value.toFloat(), padding.value.toFloat()), childPosition.value)
     }
 
     @Test
@@ -176,7 +175,7 @@
         val alignSize = Ref<IntPxSize>()
         val containerSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Container(
                 alignment = Alignment.TopStart,
@@ -197,7 +196,7 @@
                         height = sizeDp,
                         modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize.value = coordinates.size
-                            childPosition.value = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition.value = coordinates.localToGlobal(Offset(0f, 0f))
                             positionedLatch.countDown()
                         })
                 }
@@ -208,9 +207,11 @@
         assertEquals(alignSize.value, containerSize.value)
         assertEquals(IntPxSize(size, size), childSize.value)
         assertEquals(
-            PxPosition(
-                (containerSize.value!!.width.toPx() / 2 - size.toPx() / 2).round(),
-                (containerSize.value!!.height.toPx() / 2 - size.toPx() / 2).round()
+            Offset(
+                (containerSize.value!!.width.value.toFloat() / 2 - size.value.toFloat() / 2)
+                    .roundToInt().toFloat(),
+                (containerSize.value!!.height.value.toFloat() / 2 - size.value.toFloat() / 2)
+                    .roundToInt().toFloat()
             ),
             childPosition.value
         )
@@ -227,7 +228,7 @@
         val positionedLatch = CountDownLatch(2)
         val containerSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack {
                 val constraints = DpConstraints(minWidth = sizeDp * 2, minHeight = sizeDp * 2)
@@ -243,7 +244,7 @@
                             modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                                 childSize.value = coordinates.size
                                 childPosition.value =
-                                    coordinates.localToGlobal(PxPosition(0f, 0f))
+                                    coordinates.localToGlobal(Offset(0f, 0f))
                                 positionedLatch.countDown()
                             })
                     }
@@ -257,7 +258,7 @@
             containerSize.value
         )
         assertEquals(IntPxSize(size, size), childSize.value)
-        assertEquals(PxPosition(size, size), childPosition.value)
+        assertEquals(Offset(size.value.toFloat(), size.value.toFloat()), childPosition.value)
     }
 
     @Test
@@ -347,9 +348,12 @@
                 (containerSize.toIntPx() - padding.toIntPx() * 2 - childSize.toIntPx()) / 2
         val childPosition = childCoordinates!!.parentCoordinates!!.childToLocal(
             childCoordinates!!,
-            PxPosition.Origin
+            Offset.Zero
         )
-        assertEquals(PxPosition(centeringOffset, centeringOffset), childPosition)
+        assertEquals(
+            Offset(centeringOffset.value.toFloat(), centeringOffset.value.toFloat()),
+            childPosition
+        )
         assertEquals(IntPxSize(childSize.toIntPx(), childSize.toIntPx()), childCoordinates!!.size)
     }
 
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/FlowTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/FlowTest.kt
index bfff53f..d353ebc 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/FlowTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/FlowTest.kt
@@ -31,7 +31,7 @@
 import androidx.ui.layout.Stack
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
@@ -55,7 +55,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -95,7 +95,7 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = size * (i / 5)),
+                Offset(x = (size * (i % 5)).value.toFloat(), y = (size * (i / 5)).value.toFloat()),
                 childPosition[i].value
             )
         }
@@ -111,7 +111,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -150,7 +150,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = size * (i / 5)),
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -166,7 +169,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -207,7 +210,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = size * (i / 5)),
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -223,7 +229,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -267,7 +273,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = (flowWidth - size * 5) / 2 + size * (i % 5), y = size * (i / 5)),
+                Offset(
+                    x = ((flowWidth - size * 5) / 2 + size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -283,7 +292,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -326,7 +335,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = size * (i / 5)),
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -342,7 +354,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -386,7 +398,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = flowWidth - size * 5 + size * (i % 5), y = size * (i / 5)),
+                Offset(
+                    x = (flowWidth - size * 5 + size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -402,7 +417,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -445,10 +460,11 @@
                 IntPxSize(width = size, height = size),
                 childSize[i].value
             )
+            val x = (flowWidth - size * 5) * (i % 5 + 1) / 6 + size * (i % 5)
             assertEquals(
-                PxPosition(
-                    x = (flowWidth - size * 5) * (i % 5 + 1) / 6 + size * (i % 5),
-                    y = size * (i / 5)
+                Offset(
+                    x = x.value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -465,7 +481,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -509,9 +525,9 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = (flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5),
-                    y = size * (i / 5)
+                Offset(
+                    x = ((flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -528,7 +544,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -572,9 +588,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = (flowWidth - size * 5) * (i % 5 + 0.5f) / 5 + size * (i % 5),
-                    y = size * (i / 5)
+                Offset(
+                    x = ((flowWidth - size * 5) * (i % 5 + 0.5f) / 5 + size * (i % 5))
+                        .value.toFloat(),
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -591,7 +608,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -636,13 +653,13 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
+                Offset(
                     x = if (i < 10) {
-                        (flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        (flowWidth - size * 5) / 2 + size * (i % 5)
+                        ((flowWidth - size * 5) / 2 + size * (i % 5)).value.toFloat()
                     },
-                    y = size * (i / 5)
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -659,7 +676,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -704,13 +721,13 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
+                Offset(
                     x = if (i < 10) {
-                        (flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        size * (i % 5)
+                        (size * (i % 5)).value.toFloat()
                     },
-                    y = size * (i / 5)
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -727,7 +744,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -772,13 +789,13 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
+                Offset(
                     x = if (i < 10) {
-                        (flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowWidth - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        (flowWidth - size * 5) + size * (i % 5)
+                        ((flowWidth - size * 5) + size * (i % 5)).value.toFloat()
                     },
-                    y = size * (i / 5)
+                    y = (size * (i / 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -797,7 +814,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -838,7 +855,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = (size + spacing) * (i % 3), y = size * (i / 3)),
+                Offset(
+                    x = ((size + spacing) * (i % 3)).value.toFloat(),
+                    y = (size * (i / 3)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -854,7 +874,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -899,9 +919,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i % 5),
-                    y = size * 2 * (i / 5) + if (i % 2 == 0) size / 2 else IntPx.Zero
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * 2 * (i / 5) + if (i % 2 == 0) size / 2 else IntPx.Zero)
+                        .value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -918,7 +939,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -963,7 +984,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = size * 2 * (i / 5)),
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * 2 * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -979,7 +1003,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1024,9 +1048,9 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i % 5),
-                    y = size * 2 * (i / 5) + if (i % 2 == 0) size else IntPx.Zero
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = (size * 2 * (i / 5) + if (i % 2 == 0) size else IntPx.Zero).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -1045,7 +1069,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1086,7 +1110,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i % 5), y = (size + spacing) * (i / 5)),
+                Offset(
+                    x = (size * (i % 5)).value.toFloat(),
+                    y = ((size + spacing) * (i / 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1102,7 +1129,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1141,7 +1168,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1157,7 +1187,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1196,7 +1226,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1212,7 +1245,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1251,7 +1284,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1267,7 +1303,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1309,7 +1345,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = (flowHeight - size * 5) / 2 + size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = ((flowHeight - size * 5) / 2 + size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1325,7 +1364,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1367,7 +1406,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1383,7 +1425,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1427,7 +1469,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 5), y = flowHeight - size * 5 + size * (i % 5)),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = (flowHeight - size * 5 + size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1443,7 +1488,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1484,10 +1529,11 @@
                 IntPxSize(width = size, height = size),
                 childSize[i].value
             )
+            val y = (flowHeight - size * 5) * (i % 5 + 1) / 6 + size * (i % 5)
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
-                    y = (flowHeight - size * 5) * (i % 5 + 1) / 6 + size * (i % 5)
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = y.value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -1504,7 +1550,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1546,9 +1592,9 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
-                    y = (flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = ((flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -1565,7 +1611,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1607,9 +1653,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
-                    y = (flowHeight - size * 5) * (i % 5 + 0.5f) / 5 + size * (i % 5)
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
+                    y = ((flowHeight - size * 5) * (i % 5 + 0.5f) / 5 + size * (i % 5))
+                            .value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -1626,7 +1673,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1669,12 +1716,12 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
                     y = if (i < 10) {
-                        (flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        (flowHeight - size * 5) / 2 + size * (i % 5)
+                        ((flowHeight - size * 5) / 2 + size * (i % 5)).value.toFloat()
                     }
                 ),
                 childPosition[i].value
@@ -1692,7 +1739,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1735,12 +1782,12 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
                     y = if (i < 10) {
-                        (flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        size * (i % 5)
+                        (size * (i % 5)).value.toFloat()
                     }
                 ),
                 childPosition[i].value
@@ -1758,7 +1805,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1801,12 +1848,12 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * (i / 5),
+                Offset(
+                    x = (size * (i / 5)).value.toFloat(),
                     y = if (i < 10) {
-                        (flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)
+                        ((flowHeight - size * 5) * (i % 5) / 4 + size * (i % 5)).value.toFloat()
                     } else {
-                        (flowHeight - size * 5) + size * (i % 5)
+                        ((flowHeight - size * 5) + size * (i % 5)).value.toFloat()
                     }
                 ),
                 childPosition[i].value
@@ -1826,7 +1873,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1865,7 +1912,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * (i / 3), y = (size + spacing) * (i % 3)),
+                Offset(
+                    x = (size * (i / 3)).value.toFloat(),
+                    y = ((size + spacing) * (i % 3)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -1881,7 +1931,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1925,9 +1975,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(
-                    x = size * 2 * (i / 5) + if (i % 2 == 0) size / 2 else IntPx.Zero,
-                    y = size * (i % 5)
+                Offset(
+                    x = (size * 2 * (i / 5) + if (i % 2 == 0) size / 2 else IntPx.Zero)
+                            .value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -1944,7 +1995,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -1985,7 +2036,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = size * 2 * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = (size * 2 * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
@@ -2001,7 +2055,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -2044,10 +2098,11 @@
                 ),
                 childSize[i].value
             )
+            val x = (size * 2 * (i / 5) + if (i % 2 == 0) size else IntPx.Zero)
             assertEquals(
-                PxPosition(
-                    x = size * 2 * (i / 5) + if (i % 2 == 0) size else IntPx.Zero,
-                    y = size * (i % 5)
+                Offset(
+                    x = x.value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
                 ),
                 childPosition[i].value
             )
@@ -2066,7 +2121,7 @@
 
         val flowSize = Ref<IntPxSize>()
         val childSize = Array(numberOfSquares) { Ref<IntPxSize>() }
-        val childPosition = Array(numberOfSquares) { Ref<PxPosition>() }
+        val childPosition = Array(numberOfSquares) { Ref<Offset>() }
         val positionedLatch = CountDownLatch(numberOfSquares + 1)
 
         show {
@@ -2105,7 +2160,10 @@
                 childSize[i].value
             )
             assertEquals(
-                PxPosition(x = (size + spacing) * (i / 5), y = size * (i % 5)),
+                Offset(
+                    x = ((size + spacing) * (i / 5)).value.toFloat(),
+                    y = (size * (i % 5)).value.toFloat()
+                ),
                 childPosition[i].value
             )
         }
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/IntrinsicTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/IntrinsicTest.kt
index 1016f91..5a21d6c 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/IntrinsicTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/IntrinsicTest.kt
@@ -32,7 +32,7 @@
 import androidx.ui.layout.preferredWidth
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import org.junit.Assert.assertEquals
@@ -52,7 +52,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     minIntrinsicWidthSize.value = coordinates.size
@@ -73,7 +73,7 @@
 
         assertEquals(IntPxSize(10.dp.toIntPx(), 50.dp.toIntPx()), minIntrinsicWidthSize.value)
         assertEquals(IntPxSize(10.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -81,7 +81,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     minIntrinsicHeightSize.value = coordinates.size
@@ -102,7 +102,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 40.dp.toIntPx()), minIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 40.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -110,7 +110,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicWidthSize.value = coordinates.size
@@ -131,7 +131,7 @@
 
         assertEquals(IntPxSize(30.dp.toIntPx(), 50.dp.toIntPx()), maxIntrinsicWidthSize.value)
         assertEquals(IntPxSize(30.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -139,7 +139,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicHeightSize.value = coordinates.size
@@ -160,7 +160,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 60.dp.toIntPx()), maxIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 60.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -168,7 +168,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack {
                 ConstrainedBox(
@@ -193,7 +193,7 @@
 
         assertEquals(IntPxSize(5.dp.toIntPx(), 50.dp.toIntPx()), minIntrinsicWidthSize.value)
         assertEquals(IntPxSize(5.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -201,7 +201,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack {
                 ConstrainedBox(
@@ -226,7 +226,7 @@
 
         assertEquals(IntPxSize(15.dp.toIntPx(), 50.dp.toIntPx()), minIntrinsicWidthSize.value)
         assertEquals(IntPxSize(15.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -234,7 +234,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     minIntrinsicHeightSize.value = coordinates.size
@@ -257,7 +257,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 35.dp.toIntPx()), minIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 35.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -265,7 +265,7 @@
         val positionedLatch = CountDownLatch(2)
         val minIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     minIntrinsicHeightSize.value = coordinates.size
@@ -288,7 +288,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 45.dp.toIntPx()), minIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 45.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -296,7 +296,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicWidthSize.value = coordinates.size
@@ -319,7 +319,7 @@
 
         assertEquals(IntPxSize(25.dp.toIntPx(), 50.dp.toIntPx()), maxIntrinsicWidthSize.value)
         assertEquals(IntPxSize(25.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -327,7 +327,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicWidthSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicWidthSize.value = coordinates.size
@@ -350,7 +350,7 @@
 
         assertEquals(IntPxSize(35.dp.toIntPx(), 50.dp.toIntPx()), maxIntrinsicWidthSize.value)
         assertEquals(IntPxSize(35.dp.toIntPx(), 50.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -358,7 +358,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicHeightSize.value = coordinates.size
@@ -381,7 +381,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 55.dp.toIntPx()), maxIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 55.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -389,7 +389,7 @@
         val positionedLatch = CountDownLatch(2)
         val maxIntrinsicHeightSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack(modifier = Modifier.onChildPositioned { coordinates: LayoutCoordinates ->
                     maxIntrinsicHeightSize.value = coordinates.size
@@ -412,7 +412,7 @@
 
         assertEquals(IntPxSize(20.dp.toIntPx(), 65.dp.toIntPx()), maxIntrinsicHeightSize.value)
         assertEquals(IntPxSize(20.dp.toIntPx(), 65.dp.toIntPx()), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAlignTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAlignTest.kt
index 5ec5cb0..262e106 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAlignTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAlignTest.kt
@@ -38,10 +38,9 @@
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
@@ -60,9 +59,9 @@
 
         val positionedLatch = CountDownLatch(2)
         val alignSize = Ref<IntPxSize>()
-        val alignPosition = Ref<PxPosition>()
+        val alignPosition = Ref<Offset>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Container(Modifier.saveLayoutInfo(alignSize, alignPosition, positionedLatch)) {
                 Container(
@@ -80,10 +79,10 @@
         waitForDraw(root)
 
         assertEquals(IntPxSize(root.width.ipx, root.height.ipx), alignSize.value)
-        assertEquals(PxPosition(0f, 0f), alignPosition.value)
+        assertEquals(Offset(0f, 0f), alignPosition.value)
         assertEquals(IntPxSize(size, size), childSize.value)
         assertEquals(
-            PxPosition((root.width.px - size).value, (root.height.px - size).value),
+            Offset(root.width - size.value.toFloat(), root.height - size.value.toFloat()),
             childPosition.value
         )
     }
@@ -95,9 +94,9 @@
 
         val positionedLatch = CountDownLatch(2)
         val alignSize = Ref<IntPxSize>()
-        val alignPosition = Ref<PxPosition>()
+        val alignPosition = Ref<Offset>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Container(
                 Modifier.saveLayoutInfo(
@@ -121,9 +120,9 @@
         waitForDraw(root)
 
         assertEquals(IntPxSize(root.width.ipx, root.height.ipx), alignSize.value)
-        assertEquals(PxPosition(0f, 0f), alignPosition.value)
+        assertEquals(Offset(0f, 0f), alignPosition.value)
         assertEquals(IntPxSize(size, root.height.ipx), childSize.value)
-        assertEquals(PxPosition((root.width.px - size).value, 0f), childPosition.value)
+        assertEquals(Offset(root.width - size.value.toFloat(), 0f), childPosition.value)
     }
 
     @Test
@@ -133,7 +132,7 @@
 
         val positionedLatch = CountDownLatch(3)
         val childSize = Array(3) { Ref<IntPxSize>() }
-        val childPosition = Array(3) { Ref<PxPosition>() }
+        val childPosition = Array(3) { Ref<Offset>() }
         show {
             Stack(Modifier.rtl) {
                 Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
@@ -165,15 +164,18 @@
         waitForDraw(root)
 
         assertEquals(
-            PxPosition(root.width.ipx - size, 0.ipx),
+            Offset((root.width.ipx - size).value.toFloat(), 0f),
             childPosition[0].value
         )
         assertEquals(
-            PxPosition(root.width.ipx - size, (root.height.ipx - size) / 2),
+            Offset(
+                (root.width.ipx - size).value.toFloat(),
+                ((root.height.ipx - size) / 2).value.toFloat()
+            ),
             childPosition[1].value
         )
         assertEquals(
-            PxPosition(0.ipx, root.height.ipx - size),
+            Offset(0f, (root.height.ipx - size).value.toFloat()),
             childPosition[2].value
         )
     }
@@ -205,9 +207,9 @@
 
         val positionedLatch = CountDownLatch(2)
         val alignSize = Ref<IntPxSize>()
-        val alignPosition = Ref<PxPosition>()
+        val alignPosition = Ref<Offset>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Layout(
                 children = {
@@ -236,9 +238,9 @@
         waitForDraw(root)
 
         assertEquals(IntPxSize(size, size), alignSize.value)
-        assertEquals(PxPosition(0f, 0f), alignPosition.value)
+        assertEquals(Offset(0f, 0f), alignPosition.value)
         assertEquals(IntPxSize(size, size), childSize.value)
-        assertEquals(PxPosition(0f, 0f), childPosition.value)
+        assertEquals(Offset(0f, 0f), childPosition.value)
     }
 
     @Test
@@ -251,7 +253,7 @@
         val positionedLatch = CountDownLatch(2)
         val wrapSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Container(Modifier.wrapContentSize(Alignment.TopStart)) {
                 Layout(
@@ -275,7 +277,7 @@
                         ).enforce(incomingConstraints)
                         val placeable = measurable.measure(constraints)
                         layout(placeable.width, placeable.height) {
-                            placeable.place(PxPosition.Origin)
+                            placeable.place(Offset.Zero)
                         }
                     }
                 )
@@ -286,7 +288,10 @@
         assertEquals(IntPxSize(doubleSize, doubleSize), wrapSize.value)
         assertEquals(IntPxSize(size, size), childSize.value)
         assertEquals(
-            PxPosition((doubleSize - size) / 2, (doubleSize - size) / 2),
+            Offset(
+                ((doubleSize - size) / 2).value.toFloat(),
+                ((doubleSize - size) / 2).value.toFloat()
+            ),
             childPosition.value
         )
     }
@@ -392,9 +397,9 @@
 
         val positionedLatch = CountDownLatch(2)
         val alignSize = Ref<IntPxSize>()
-        val alignPosition = Ref<PxPosition>()
+        val alignPosition = Ref<Offset>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Layout(
                 children = {
@@ -425,9 +430,9 @@
 
         assertEquals(IntPxSize(childSizeIpx, childSizeIpx), childSize.value)
         assertEquals(
-            PxPosition(
-                alignSize.value!!.width - childSizeIpx,
-                alignSize.value!!.height - childSizeIpx
+            Offset(
+                (alignSize.value!!.width - childSizeIpx).value.toFloat(),
+                (alignSize.value!!.height - childSizeIpx).value.toFloat()
             ),
             childPosition.value
         )
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAspectRatioTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAspectRatioTest.kt
index 04a71bf..9c6e443b 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAspectRatioTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutAspectRatioTest.kt
@@ -25,7 +25,7 @@
 import androidx.ui.layout.aspectRatio
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import org.junit.Assert.assertEquals
@@ -91,7 +91,7 @@
     private fun getSize(aspectRatio: Float, childContraints: Constraints): IntPxSize {
         val positionedLatch = CountDownLatch(1)
         val size = Ref<IntPxSize>()
-        val position = Ref<PxPosition>()
+        val position = Ref<Offset>()
         show {
             Layout(@Composable {
                 Container(
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutOffsetTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutOffsetTest.kt
index 0c1ef72..947057d 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutOffsetTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutOffsetTest.kt
@@ -38,8 +38,6 @@
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
-import androidx.ui.unit.round
 import org.junit.Assert
 import org.junit.Assume
 import org.junit.Before
@@ -75,8 +73,8 @@
                     .wrapContentSize(Alignment.TopStart)
                     .offset(offsetX, offsetY)
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        positionX = coordinates.globalPosition.x.px.round()
-                        positionY = coordinates.globalPosition.y.px.round()
+                        positionX = coordinates.globalPosition.x.roundToInt().ipx
+                        positionY = coordinates.globalPosition.y.roundToInt().ipx
                     }
             ) {
             }
@@ -106,8 +104,8 @@
                     .wrapContentSize(Alignment.TopStart)
                     .offset(offsetX, offsetY)
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        positionX = coordinates.globalPosition.x.px.round()
-                        positionY = coordinates.globalPosition.y.px.round()
+                        positionX = coordinates.globalPosition.x.roundToInt().ipx
+                        positionY = coordinates.globalPosition.y.roundToInt().ipx
                     }
             ) {
                 // TODO(popam): this box should not be needed after b/154758475 is fixed.
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutPaddingTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutPaddingTest.kt
index 4619854..9cfbee9 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutPaddingTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutPaddingTest.kt
@@ -41,11 +41,10 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.min
-import androidx.ui.unit.toPx
 import androidx.ui.unit.toPxSize
 import org.junit.Assert
 import org.junit.Assert.assertEquals
@@ -251,7 +250,7 @@
 
         val drawLatch = CountDownLatch(3)
         val childSize = Array(3) { IntPxSize(0.ipx, 0.ipx) }
-        val childPosition = Array(3) { PxPosition(0f, 0f) }
+        val childPosition = Array(3) { Offset(0f, 0f) }
 
         // ltr: P1 S P2 | S P3 | P1 S
         // rtl:    S P1 | P3 S | P2 S P1
@@ -262,7 +261,7 @@
                         .preferredSize(sizeDp, sizeDp)
                         .onPositioned { coordinates: LayoutCoordinates ->
                             childSize[0] = coordinates.size
-                            childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -273,7 +272,7 @@
                         .preferredSize(sizeDp, sizeDp)
                         .onPositioned { coordinates: LayoutCoordinates ->
                             childSize[1] = coordinates.size
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -284,7 +283,7 @@
                         .preferredSize(sizeDp, sizeDp)
                         .onPositioned { coordinates: LayoutCoordinates ->
                             childSize[2] = coordinates.size
-                            childPosition[2] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[2] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -297,17 +296,20 @@
 
         val rootWidth = root.width.ipx
 //        S P1 | P3 S | P2 S P1
-        assertEquals(PxPosition(rootWidth - padding1 - size, 0.ipx), childPosition[0])
+        assertEquals(Offset((rootWidth - padding1 - size).value.toFloat(), 0f), childPosition[0])
         assertEquals(IntPxSize(size, size), childSize[0])
 
         assertEquals(
-            PxPosition(rootWidth - padding1 - padding2 - size * 2, 0.ipx),
+            Offset((rootWidth - padding1 - padding2 - size * 2).value.toFloat(), 0f),
             childPosition[1]
         )
         assertEquals(IntPxSize(size, size), childSize[1])
 
         assertEquals(
-            PxPosition(rootWidth - size * 3 - padding1 * 2 - padding2 - padding3, 0.ipx),
+            Offset(
+                (rootWidth - size * 3 - padding1 * 2 - padding2 - padding3).value.toFloat(),
+                0f
+            ),
             childPosition[2]
         )
         assertEquals(IntPxSize(size, size), childSize[2])
@@ -319,7 +321,7 @@
         val size = 300.ipx
         val paddingDp = padding.toDp()
         val latch = CountDownLatch(1)
-        val resultPosition = Ref<PxPosition>()
+        val resultPosition = Ref<Offset>()
         val resultSize = Ref<IntPxSize>()
 
         show {
@@ -350,7 +352,7 @@
             resultSize.value?.toPxSize()
         )
         assertEquals(
-            PxPosition(rootWidth - size + padding, 0.ipx),
+            Offset((rootWidth - size + padding).value.toFloat(), 0f),
             resultPosition.value
         )
     }
@@ -365,7 +367,7 @@
 
         val drawLatch = CountDownLatch(1)
         var childSize = IntPxSize(-1.ipx, -1.ipx)
-        var childPosition = PxPosition(-1f, -1f)
+        var childPosition = Offset(-1f, -1f)
         show {
             Stack(Modifier.fillMaxSize()) {
                 ConstrainedBox(
@@ -375,7 +377,7 @@
                     val children = @Composable {
                         Container(Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize = coordinates.size
-                            childPosition = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }) {
                         }
@@ -394,7 +396,7 @@
         val left = ((root.width.ipx - size) / 2) + paddingPx
         val top = ((root.height.ipx - size) / 2) + paddingPx
         assertEquals(
-            PxPosition(left.toPx().value, top.toPx().value),
+            Offset(left.value.toFloat(), top.value.toFloat()),
             childPosition
         )
     }
@@ -411,7 +413,7 @@
 
         val drawLatch = CountDownLatch(1)
         var childSize = IntPxSize(-1.ipx, -1.ipx)
-        var childPosition = PxPosition(-1f, -1f)
+        var childPosition = Offset(-1f, -1f)
         show {
             Stack(Modifier.fillMaxSize()) {
                 ConstrainedBox(
@@ -421,7 +423,7 @@
                     val children = @Composable {
                         Container(Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize = coordinates.size
-                            childPosition = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }) {
                         }
@@ -449,7 +451,7 @@
         val viewLeft = ((root.width.ipx - size) / 2) + paddingLeft
         val viewTop = ((root.height.ipx - size) / 2) + paddingTop
         assertEquals(
-            PxPosition(viewLeft.toPx().value, viewTop.toPx().value),
+            Offset(viewLeft.value.toFloat(), viewTop.value.toFloat()),
             childPosition
         )
     }
@@ -464,7 +466,7 @@
 
         val drawLatch = CountDownLatch(1)
         var childSize = IntPxSize(-1.ipx, -1.ipx)
-        var childPosition = PxPosition(-1f, -1f)
+        var childPosition = Offset(-1f, -1f)
         show {
             Stack(Modifier.fillMaxSize()) {
                 ConstrainedBox(
@@ -474,7 +476,7 @@
                     paddingContainer {
                         Container(Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize = coordinates.size
-                            childPosition = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }) {
                         }
@@ -490,7 +492,7 @@
         assertEquals(IntPxSize(0.ipx, 0.ipx), childSize)
         val left = ((root.width.ipx - size) / 2) + paddingPx
         val top = ((root.height.ipx - size) / 2) + paddingPx
-        assertEquals(PxPosition(left.toPx().value, top.toPx().value), childPosition)
+        assertEquals(Offset(left.value.toFloat(), top.value.toFloat()), childPosition)
     }
 
     /**
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutSizeTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutSizeTest.kt
index 577a6f6..4206678 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutSizeTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutSizeTest.kt
@@ -52,7 +52,7 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.min
@@ -75,7 +75,7 @@
 
         val positionedLatch = CountDownLatch(6)
         val size = MutableList(6) { Ref<IntPxSize>() }
-        val position = MutableList(6) { Ref<PxPosition>() }
+        val position = MutableList(6) { Ref<Offset>() }
         show {
             Stack {
                 Column {
@@ -122,22 +122,22 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[0].value)
-        assertEquals(PxPosition.Origin, position[0].value)
+        assertEquals(Offset.Zero, position[0].value)
 
         assertEquals(IntPxSize(0.ipx, sizeIpx), size[1].value)
-        assertEquals(PxPosition(0.ipx, sizeIpx), position[1].value)
+        assertEquals(Offset(0f, sizeIpx.value.toFloat()), position[1].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[2].value)
-        assertEquals(PxPosition(0.ipx, sizeIpx * 2), position[2].value)
+        assertEquals(Offset(0f, (sizeIpx * 2).value.toFloat()), position[2].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[3].value)
-        assertEquals(PxPosition(0.ipx, sizeIpx * 3), position[3].value)
+        assertEquals(Offset(0f, (sizeIpx * 3).value.toFloat()), position[3].value)
 
         assertEquals(IntPxSize((sizeDp * 2).toIntPx(), sizeIpx), size[4].value)
-        assertEquals(PxPosition(0.ipx, sizeIpx * 4), position[4].value)
+        assertEquals(Offset(0f, (sizeIpx * 4).value.toFloat()), position[4].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[5].value)
-        assertEquals(PxPosition(0.ipx, sizeIpx * 5), position[5].value)
+        assertEquals(Offset(0f, (sizeIpx * 5).value.toFloat()), position[5].value)
     }
 
     @Test
@@ -147,7 +147,7 @@
 
         val positionedLatch = CountDownLatch(6)
         val size = MutableList(6) { Ref<IntPxSize>() }
-        val position = MutableList(6) { Ref<PxPosition>() }
+        val position = MutableList(6) { Ref<Offset>() }
         show {
             Stack {
                 Row {
@@ -194,22 +194,22 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[0].value)
-        assertEquals(PxPosition.Origin, position[0].value)
+        assertEquals(Offset.Zero, position[0].value)
 
         assertEquals(IntPxSize(sizeIpx, 0.ipx), size[1].value)
-        assertEquals(PxPosition(sizeIpx, 0.ipx), position[1].value)
+        assertEquals(Offset(sizeIpx.value.toFloat(), 0f), position[1].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[2].value)
-        assertEquals(PxPosition(sizeIpx * 2, 0.ipx), position[2].value)
+        assertEquals(Offset((sizeIpx * 2).value.toFloat(), 0f), position[2].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[3].value)
-        assertEquals(PxPosition(sizeIpx * 3, 0.ipx), position[3].value)
+        assertEquals(Offset((sizeIpx * 3).value.toFloat(), 0f), position[3].value)
 
         assertEquals(IntPxSize(sizeIpx, (sizeDp * 2).toIntPx()), size[4].value)
-        assertEquals(PxPosition(sizeIpx * 4, 0.ipx), position[4].value)
+        assertEquals(Offset((sizeIpx * 4).value.toFloat(), 0f), position[4].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[5].value)
-        assertEquals(PxPosition(sizeIpx * 5, 0.ipx), position[5].value)
+        assertEquals(Offset((sizeIpx * 5).value.toFloat(), 0f), position[5].value)
     }
 
     @Test
@@ -219,7 +219,7 @@
 
         val positionedLatch = CountDownLatch(5)
         val size = MutableList(5) { Ref<IntPxSize>() }
-        val position = MutableList(5) { Ref<PxPosition>() }
+        val position = MutableList(5) { Ref<Offset>() }
         show {
             Stack {
                 Row {
@@ -261,19 +261,19 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[0].value)
-        assertEquals(PxPosition.Origin, position[0].value)
+        assertEquals(Offset.Zero, position[0].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[1].value)
-        assertEquals(PxPosition(sizeIpx, 0.ipx), position[1].value)
+        assertEquals(Offset(sizeIpx.value.toFloat(), 0f), position[1].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[2].value)
-        assertEquals(PxPosition(sizeIpx * 2, 0.ipx), position[2].value)
+        assertEquals(Offset((sizeIpx * 2).value.toFloat(), 0f), position[2].value)
 
         assertEquals(IntPxSize((sizeDp * 2).toIntPx(), (sizeDp * 2).toIntPx()), size[3].value)
-        assertEquals(PxPosition(sizeIpx * 3, 0.ipx), position[3].value)
+        assertEquals(Offset((sizeIpx * 3).value.toFloat(), 0f), position[3].value)
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), size[4].value)
-        assertEquals(PxPosition((sizeDp * 5).toIntPx(), 0.ipx), position[4].value)
+        assertEquals(Offset((sizeDp * 5).toIntPx().value.toFloat(), 0f), position[4].value)
     }
 
     @Test
@@ -284,7 +284,7 @@
         val positionedLatch = CountDownLatch(2)
         val constrainedBoxSize = Ref<IntPxSize>()
         val childSize = Ref<IntPxSize>()
-        val childPosition = Ref<PxPosition>()
+        val childPosition = Ref<Offset>()
         show {
             Stack {
                 Container(width = sizeDp, height = sizeDp) {
@@ -312,7 +312,7 @@
 
         assertEquals(IntPxSize(size, size), constrainedBoxSize.value)
         assertEquals(IntPxSize(size, size), childSize.value)
-        assertEquals(PxPosition.Origin, childPosition.value)
+        assertEquals(Offset.Zero, childPosition.value)
     }
 
     @Test
@@ -322,7 +322,7 @@
 
         val positionedLatch = CountDownLatch(4)
         val size = MutableList(4) { Ref<IntPxSize>() }
-        val position = MutableList(4) { Ref<PxPosition>() }
+        val position = MutableList(4) { Ref<Offset>() }
         show {
             Stack {
                 Row {
@@ -386,7 +386,7 @@
 
         val positionedLatch = CountDownLatch(1)
         val boxSize = Ref<IntPxSize>()
-        val boxPosition = Ref<PxPosition>()
+        val boxPosition = Ref<Offset>()
         show {
             Box(Modifier.wrapContentSize(Alignment.TopStart)
                 .size(sizeDp * 2)
@@ -397,7 +397,12 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(sizeIpx, sizeIpx), boxSize.value)
-        assertEquals(PxPosition(sizeIpx / 2, sizeIpx / 2), boxPosition.value)
+        assertEquals(
+            Offset(
+                (sizeIpx / 2).value.toFloat(),
+                (sizeIpx / 2).value.toFloat()),
+            boxPosition.value
+        )
     }
 
     @Test
@@ -407,7 +412,7 @@
 
         val positionedLatch = CountDownLatch(1)
         val boxSize = Ref<IntPxSize>()
-        val boxPosition = Ref<PxPosition>()
+        val boxPosition = Ref<Offset>()
         show {
             Box(Modifier.wrapContentSize(Alignment.TopStart)
                 .size(sizeDp)
@@ -418,7 +423,10 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(sizeIpx * 2, sizeIpx * 2), boxSize.value)
-        assertEquals(PxPosition(-sizeIpx / 2, -sizeIpx / 2), boxPosition.value)
+        assertEquals(
+            Offset((-sizeIpx / 2).value.toFloat(), (-sizeIpx / 2).value.toFloat()),
+            boxPosition.value
+        )
     }
 
     @Test
@@ -1014,7 +1022,7 @@
 
         val positionedLatch = CountDownLatch(1)
         val size = Ref<IntPxSize>()
-        val position = Ref<PxPosition>()
+        val position = Ref<Offset>()
         show {
             Layout(@Composable {
                 Stack {
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutTest.kt
index f7e2304..18b6ec1 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/LayoutTest.kt
@@ -23,7 +23,6 @@
 import android.view.ViewTreeObserver
 import androidx.compose.Composable
 import androidx.compose.Recomposer
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Alignment
 import androidx.ui.core.AlignmentLine
 import androidx.ui.core.AndroidOwner
@@ -47,15 +46,12 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.isFinite
 import androidx.ui.unit.max
-import androidx.ui.unit.px
-import androidx.ui.unit.round
-import androidx.ui.unit.toPx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertTrue
@@ -64,10 +60,12 @@
 import org.junit.Rule
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
 
 open class LayoutTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     lateinit var activity: TestActivity
@@ -141,11 +139,11 @@
 
     internal fun Modifier.saveLayoutInfo(
         size: Ref<IntPxSize>,
-        position: Ref<PxPosition>,
+        position: Ref<Offset>,
         positionedLatch: CountDownLatch
     ): Modifier = this.onPositioned { coordinates ->
         size.value = IntPxSize(coordinates.size.width, coordinates.size.height)
-        position.value = coordinates.localToGlobal(PxPosition(0f, 0f))
+        position.value = coordinates.localToGlobal(Offset(0f, 0f))
         positionedLatch.countDown()
     }
 
@@ -267,11 +265,11 @@
         }
     }
 
-    internal fun assertEquals(expected: PxPosition?, actual: PxPosition?) {
+    internal fun assertEquals(expected: Offset?, actual: Offset?) {
         assertNotNull("Null expected position", expected)
-        expected as PxPosition
+        expected as Offset
         assertNotNull("Null actual position", actual)
-        actual as PxPosition
+        actual as Offset
 
         assertEquals(
             "Expected x ${expected.x} but obtained ${actual.x}",
@@ -309,17 +307,17 @@
             layoutDirection: LayoutDirection
         ): List<IntPx> {
             val positions = mutableListOf<IntPx>()
-            var current = 0.px
+            var current = 0f
             val usedSpace = size.fold(0.ipx) { sum, e -> sum + e }
             val step = if (size.size < 2) {
-                0.px
+                0f
             } else {
-                (totalSize - usedSpace).toPx() * 2 / (size.lastIndex * size.size)
+                (totalSize - usedSpace).value.toFloat() * 2 / (size.lastIndex * size.size)
             }
             size.forEachIndexed { i, childSize ->
                 current += step * i
-                positions.add(current.round())
-                current += childSize.toPx()
+                positions.add(current.roundToInt().ipx)
+                current += childSize.value.toFloat()
             }
             return positions
         }
@@ -332,23 +330,23 @@
             layoutDirection: LayoutDirection
         ): List<IntPx> {
             val positions = mutableListOf<IntPx>()
-            var current = 0.px
+            var current = 0f
             if (layoutDirection == LayoutDirection.Rtl) {
                 size.forEach {
-                    positions.add(current.round())
-                    current += it
+                    positions.add(current.roundToInt().ipx)
+                    current += it.value.toFloat()
                 }
             } else {
                 val usedSpace = size.fold(0.ipx) { sum, e -> sum + e }
                 val step = if (size.size < 2) {
-                    0.px
+                    0f
                 } else {
-                    (totalSize - usedSpace).toPx() * 2 / (size.lastIndex * size.size)
+                    (totalSize - usedSpace).value.toFloat() * 2 / (size.lastIndex * size.size)
                 }
                 size.forEachIndexed { i, childSize ->
                     current += step * i
-                    positions.add(current.round())
-                    current += childSize.toPx()
+                    positions.add(current.roundToInt().ipx)
+                    current += childSize.value.toFloat()
                 }
             }
             return positions
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/OnPositionedTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/OnPositionedTest.kt
index 751f701..50b867d 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/OnPositionedTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/OnPositionedTest.kt
@@ -37,11 +37,10 @@
 import androidx.ui.layout.fillMaxSize
 import androidx.ui.layout.padding
 import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.min
-import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert
 import org.junit.Assert.assertTrue
@@ -84,8 +83,8 @@
 
     @Test
     fun simplePaddingWithChildPositioned() = with(density) {
-        val paddingLeftPx = 100.px
-        val paddingTopPx = 120.px
+        val paddingLeftPx = 100f
+        val paddingTopPx = 120f
         var realLeft: Float? = null
         var realTop: Float? = null
 
@@ -108,15 +107,15 @@
         }
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
-        assertThat(realLeft?.px).isEqualTo(paddingLeftPx)
-        assertThat(realTop?.px).isEqualTo(paddingTopPx)
+        assertThat(realLeft).isEqualTo(paddingLeftPx)
+        assertThat(realTop).isEqualTo(paddingTopPx)
     }
 
     @Test
     fun nestedLayoutCoordinates() = with(density) {
-        val firstPaddingPx = 10.px
-        val secondPaddingPx = 20.px
-        val thirdPaddingPx = 30.px
+        val firstPaddingPx = 10f
+        val secondPaddingPx = 20f
+        val thirdPaddingPx = 30f
         var gpCoordinates: LayoutCoordinates? = null
         var childCoordinates: LayoutCoordinates? = null
 
@@ -145,13 +144,13 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         // global position
-        val gPos = childCoordinates!!.localToGlobal(PxPosition.Origin).x
-        assertThat(gPos).isEqualTo((firstPaddingPx + secondPaddingPx + thirdPaddingPx).value)
+        val gPos = childCoordinates!!.localToGlobal(Offset.Zero).x
+        assertThat(gPos).isEqualTo((firstPaddingPx + secondPaddingPx + thirdPaddingPx))
         // Position in grandparent Px(value=50.0)
-        val gpPos = gpCoordinates!!.childToLocal(childCoordinates!!, PxPosition.Origin).x
-        assertThat(gpPos).isEqualTo((secondPaddingPx + thirdPaddingPx).value)
+        val gpPos = gpCoordinates!!.childToLocal(childCoordinates!!, Offset.Zero).x
+        assertThat(gpPos).isEqualTo((secondPaddingPx + thirdPaddingPx))
         // local position
-        assertThat(childCoordinates!!.positionInParent.x).isEqualTo(thirdPaddingPx.value)
+        assertThat(childCoordinates!!.positionInParent.x).isEqualTo(thirdPaddingPx)
     }
 
     @Test
@@ -184,10 +183,10 @@
     @Test
     fun globalCoordinatesAreInActivityCoordinates() = with(density) {
         val padding = 30
-        val localPosition = PxPosition.Origin
-        val globalPosition = PxPosition(padding.ipx, padding.ipx)
-        var realGlobalPosition: PxPosition? = null
-        var realLocalPosition: PxPosition? = null
+        val localPosition = Offset.Zero
+        val globalPosition = Offset(padding.toFloat(), padding.toFloat())
+        var realGlobalPosition: Offset? = null
+        var realLocalPosition: Offset? = null
 
         val positionedLatch = CountDownLatch(1)
         activityTestRule.runOnUiThread(object : Runnable {
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/RowColumnTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/RowColumnTest.kt
index 3a8a3f5..3bd019a 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/RowColumnTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/RowColumnTest.kt
@@ -50,15 +50,12 @@
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.isFinite
 import androidx.ui.unit.max
 import androidx.ui.unit.min
-import androidx.ui.unit.px
-import androidx.ui.unit.round
-import androidx.ui.unit.toPx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertTrue
@@ -81,7 +78,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOf(IntPxSize(-1.ipx, -1.ipx), IntPxSize(-1.ipx, -1.ipx))
-        val childPosition = arrayOf(PxPosition(-1f, -1f), PxPosition(-1f, -1f))
+        val childPosition = arrayOf(Offset(-1f, -1f), Offset(-1f, -1f))
         show {
             Container(alignment = Alignment.TopStart) {
                 Row {
@@ -90,7 +87,7 @@
                         height = sizeDp,
                         modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize[0] = coordinates.size
-                            childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                     ) {
@@ -101,7 +98,7 @@
                         height = (sizeDp * 2),
                         modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize[1] = coordinates.size
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                     ) {
@@ -119,8 +116,8 @@
             IntPxSize((sizeDp.toPx() * 2).roundToInt().ipx, (sizeDp.toPx() * 2).roundToInt().ipx),
             childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(size.toPx().value, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(size.value.toFloat(), 0f), childPosition[1])
     }
 
     @Test
@@ -131,7 +128,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Container(alignment = Alignment.TopStart) {
                 Row {
@@ -139,7 +136,7 @@
                         Modifier.weight(1f)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -151,7 +148,7 @@
                         Modifier.weight(2f)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -165,18 +162,18 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
         assertEquals(
-            IntPxSize((rootWidth / 3).round(), childrenHeight),
+            IntPxSize((rootWidth / 3f).roundToInt().ipx, childrenHeight),
             childSize[0]
         )
         assertEquals(
-            IntPxSize((rootWidth * 2 / 3).round(), childrenHeight),
+            IntPxSize((rootWidth * 2f / 3f).roundToInt().ipx, childrenHeight),
             childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition((rootWidth / 3).round().toPx().value, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset((rootWidth / 3f).roundToInt().toFloat(), 0f), childPosition[1])
     }
 
     @Test
@@ -188,7 +185,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Container(alignment = Alignment.TopStart) {
                 Row {
@@ -196,7 +193,7 @@
                         Modifier.weight(1f, fill = false)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -208,7 +205,7 @@
                         Modifier.weight(2f, fill = false)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -225,8 +222,8 @@
 
         assertEquals(IntPxSize(childrenWidth, childrenHeight), childSize[0])
         assertEquals(IntPxSize(childrenWidth, childrenHeight * 2), childSize[1])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(childrenWidth.toPx().value, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(childrenWidth.value.toFloat(), 0f), childPosition[1])
     }
 
     @Test
@@ -236,7 +233,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOf(IntPxSize(-1.ipx, -1.ipx), IntPxSize(-1.ipx, -1.ipx))
-        val childPosition = arrayOf(PxPosition(-1f, -1f), PxPosition(-1f, -1f))
+        val childPosition = arrayOf(Offset(-1f, -1f), Offset(-1f, -1f))
         show {
             Container(alignment = Alignment.TopStart) {
                 Column {
@@ -245,7 +242,7 @@
                         height = sizeDp,
                         modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize[0] = coordinates.size
-                            childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                     ) {
@@ -255,7 +252,7 @@
                         height = (sizeDp * 2),
                         modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
                             childSize[1] = coordinates.size
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                     ) {
@@ -273,8 +270,8 @@
             IntPxSize((sizeDp.toPx() * 2).roundToInt().ipx, (sizeDp.toPx() * 2).roundToInt().ipx),
             childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, size.toPx().value), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, size.value.toFloat()), childPosition[1])
     }
 
     @Test
@@ -285,7 +282,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Container(alignment = Alignment.TopStart) {
                 Column {
@@ -293,7 +290,7 @@
                         Modifier.weight(1f)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -305,7 +302,7 @@
                         Modifier.weight(2f)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -319,16 +316,16 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootHeight = root.height.px
+        val rootHeight = root.height
 
         assertEquals(
-            IntPxSize(childrenWidth, (rootHeight / 3).round()), childSize[0]
+            IntPxSize(childrenWidth, (rootHeight / 3f).roundToInt().ipx), childSize[0]
         )
         assertEquals(
-            IntPxSize(childrenWidth, (rootHeight * 2 / 3).round()), childSize[1]
+            IntPxSize(childrenWidth, (rootHeight * 2f / 3f).roundToInt().ipx), childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, (rootHeight / 3).round().toPx().value), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, (rootHeight / 3f).roundToInt().toFloat()), childPosition[1])
     }
 
     @Test
@@ -340,7 +337,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Container(alignment = Alignment.TopStart) {
                 Column {
@@ -348,7 +345,7 @@
                         Modifier.weight(1f, fill = false)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -359,7 +356,7 @@
                         Modifier.weight(2f, fill = false)
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             },
                         width = width,
@@ -378,17 +375,17 @@
         assertEquals(
             IntPxSize(childrenWidth, childrenHeight), childSize[1]
         )
-        assertEquals(PxPosition(0.0f, 0.0f), childPosition[0])
-        assertEquals(PxPosition(0.0f, childrenHeight.toPx().value), childPosition[1])
+        assertEquals(Offset(0.0f, 0.0f), childPosition[0])
+        assertEquals(Offset(0.0f, childrenHeight.value.toFloat()), childPosition[1])
     }
 
     @Test
     fun testRow_doesNotPlaceChildrenOutOfBounds_becauseOfRoundings() = with(density) {
-        val expectedRowWidth = 11.ipx
-        val leftPadding = 1.px
-        var rowWidth = 0.ipx
-        val width = Array(2) { 0.ipx }
-        val x = Array(2) { 0.px }
+        val expectedRowWidth = 11f
+        val leftPadding = 1f
+        var rowWidth = 0f
+        val width = Array(2) { 0f }
+        val x = Array(2) { 0f }
         val latch = CountDownLatch(2)
         show {
             Row(
@@ -396,14 +393,14 @@
                     .padding(start = leftPadding.toDp())
                     .preferredWidthIn(maxWidth = expectedRowWidth.toDp())
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        rowWidth = coordinates.size.width
+                        rowWidth = coordinates.size.width.value.toFloat()
                     }
             ) {
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            width[0] = coordinates.size.width
-                            x[0] = coordinates.globalPosition.x.px
+                            width[0] = coordinates.size.width.value.toFloat()
+                            x[0] = coordinates.globalPosition.x
                             latch.countDown()
                         }
                 ) {
@@ -411,8 +408,8 @@
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            width[1] = coordinates.size.width
-                            x[1] = coordinates.globalPosition.x.px
+                            width[1] = coordinates.size.width.value.toFloat()
+                            x[1] = coordinates.globalPosition.x
                             latch.countDown()
                         }
                 ) {
@@ -430,11 +427,11 @@
 
     @Test
     fun testRow_isNotLargerThanItsChildren_becauseOfRoundings() = with(density) {
-        val expectedRowWidth = 8.ipx
-        val leftPadding = 1.px
-        var rowWidth = 0.ipx
-        val width = Array(3) { 0.ipx }
-        val x = Array(3) { 0.px }
+        val expectedRowWidth = 8f
+        val leftPadding = 1f
+        var rowWidth = 0f
+        val width = Array(3) { 0f }
+        val x = Array(3) { 0f }
         val latch = CountDownLatch(3)
         show {
             Row(
@@ -442,14 +439,14 @@
                     .padding(start = leftPadding.toDp())
                     .preferredWidthIn(maxWidth = expectedRowWidth.toDp())
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        rowWidth = coordinates.size.width
+                        rowWidth = coordinates.size.width.value.toFloat()
                     }
             ) {
                 Container(
                     Modifier.weight(2f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            width[0] = coordinates.size.width
-                            x[0] = coordinates.globalPosition.x.px
+                            width[0] = coordinates.size.width.value.toFloat()
+                            x[0] = coordinates.globalPosition.x
                             latch.countDown()
                         }
                 ) {
@@ -457,8 +454,8 @@
                 Container(
                     Modifier.weight(2f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            width[1] = coordinates.size.width
-                            x[1] = coordinates.globalPosition.x.px
+                            width[1] = coordinates.size.width.value.toFloat()
+                            x[1] = coordinates.globalPosition.x
                             latch.countDown()
                         }
                 ) {
@@ -466,8 +463,8 @@
                 Container(
                     Modifier.weight(3f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            width[2] = coordinates.size.width
-                            x[2] = coordinates.globalPosition.x.px
+                            width[2] = coordinates.size.width.value.toFloat()
+                            x[2] = coordinates.globalPosition.x
                             latch.countDown()
                         }
                 ) {
@@ -486,11 +483,11 @@
 
     @Test
     fun testColumn_isNotLargetThanItsChildren_becauseOfRoundings() = with(density) {
-        val expectedColumnHeight = 8.ipx
-        val topPadding = 1.px
-        var columnHeight = 0.ipx
-        val height = Array(3) { 0.ipx }
-        val y = Array(3) { 0.px }
+        val expectedColumnHeight = 8f
+        val topPadding = 1f
+        var columnHeight = 0f
+        val height = Array(3) { 0f }
+        val y = Array(3) { 0f }
         val latch = CountDownLatch(3)
         show {
             Column(
@@ -498,14 +495,14 @@
                     .padding(top = topPadding.toDp())
                     .preferredHeightIn(maxHeight = expectedColumnHeight.toDp())
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        columnHeight = coordinates.size.height
+                        columnHeight = coordinates.size.height.value.toFloat()
                     }
             ) {
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            height[0] = coordinates.size.height
-                            y[0] = coordinates.globalPosition.y.px
+                            height[0] = coordinates.size.height.value.toFloat()
+                            y[0] = coordinates.globalPosition.y
                             latch.countDown()
                         }
                 ) {
@@ -513,8 +510,8 @@
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            height[1] = coordinates.size.height
-                            y[1] = coordinates.globalPosition.y.px
+                            height[1] = coordinates.size.height.value.toFloat()
+                            y[1] = coordinates.globalPosition.y
                             latch.countDown()
                         }
                 ) {
@@ -522,8 +519,8 @@
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            height[2] = coordinates.size.height
-                            y[2] = coordinates.globalPosition.y.px
+                            height[2] = coordinates.size.height.value.toFloat()
+                            y[2] = coordinates.globalPosition.y
                             latch.countDown()
                         }
                 ) {
@@ -542,11 +539,11 @@
 
     @Test
     fun testColumn_doesNotPlaceChildrenOutOfBounds_becauseOfRoundings() = with(density) {
-        val expectedColumnHeight = 11.ipx
-        val topPadding = 1.px
-        var columnHeight = 0.ipx
-        val height = Array(2) { 0.ipx }
-        val y = Array(2) { 0.px }
+        val expectedColumnHeight = 11f
+        val topPadding = 1f
+        var columnHeight = 0f
+        val height = Array(2) { 0f }
+        val y = Array(2) { 0f }
         val latch = CountDownLatch(2)
         show {
             Column(
@@ -554,14 +551,14 @@
                     .padding(top = topPadding.toDp())
                     .preferredHeightIn(maxHeight = expectedColumnHeight.toDp())
                     .onPositioned { coordinates: LayoutCoordinates ->
-                        columnHeight = coordinates.size.height
+                        columnHeight = coordinates.size.height.value.toFloat()
                     }
             ) {
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            height[0] = coordinates.size.height
-                            y[0] = coordinates.globalPosition.y.px
+                            height[0] = coordinates.size.height.value.toFloat()
+                            y[0] = coordinates.globalPosition.y
                             latch.countDown()
                         }
                 ) {
@@ -569,8 +566,8 @@
                 Container(
                     Modifier.weight(1f)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            height[1] = coordinates.size.height
-                            y[1] = coordinates.globalPosition.y.px
+                            height[1] = coordinates.size.height.value.toFloat()
+                            y[1] = coordinates.globalPosition.y
                             latch.countDown()
                         }
                 ) {
@@ -596,7 +593,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOf(IntPxSize(-1.ipx, -1.ipx), IntPxSize(-1.ipx, -1.ipx))
-        val childPosition = arrayOf(PxPosition(-1f, -1f), PxPosition(-1f, -1f))
+        val childPosition = arrayOf(Offset(-1f, -1f), Offset(-1f, -1f))
         show {
             Row {
                     Container(
@@ -605,7 +602,7 @@
                         modifier = Modifier.fillMaxHeight()
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             }
                     ) {
@@ -617,7 +614,7 @@
                         modifier = Modifier.fillMaxHeight()
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             }
                     ) {
@@ -634,8 +631,8 @@
             IntPxSize((sizeDp.toPx() * 2).roundToInt().ipx, root.height.ipx),
             childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(size.toPx().value, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(size.value.toFloat(), 0f), childPosition[1])
     }
 
     @Test
@@ -645,7 +642,7 @@
 
         val drawLatch = CountDownLatch(3)
         val childSize = arrayOfNulls<IntPxSize>(3)
-        val childPosition = arrayOfNulls<PxPosition>(3)
+        val childPosition = arrayOfNulls<Offset>(3)
         show {
             Row(Modifier.fillMaxHeight(), verticalGravity = Alignment.CenterVertically) {
                     Container(
@@ -686,20 +683,23 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootHeight = root.height.px
+        val rootHeight = root.height
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
         assertEquals(
-            PxPosition(size.toPx().value, ((rootHeight - size.toPx()) / 2).round().toPx().value),
+            Offset(
+                size.value.toFloat(),
+                ((rootHeight - size.value.toFloat()) / 2f).roundToInt().toFloat()
+            ),
             childPosition[1]
         )
 
         assertEquals(IntPxSize(size, size), childSize[2])
-        assertEquals(PxPosition((size.toPx() * 2).value,
-            (rootHeight - size.toPx()).value),
+        assertEquals(Offset((size.value.toFloat() * 2),
+            (rootHeight - size.value.toFloat())),
             childPosition[2])
     }
 
@@ -710,7 +710,7 @@
 
         val drawLatch = CountDownLatch(3)
         val childSize = arrayOfNulls<IntPxSize>(3)
-        val childPosition = arrayOfNulls<PxPosition>(3)
+        val childPosition = arrayOfNulls<Offset>(3)
         show {
             Row(Modifier.fillMaxHeight()) {
                 Container(
@@ -752,20 +752,23 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootHeight = root.height.px
+        val rootHeight = root.height
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
         assertEquals(
-            PxPosition(size.toPx().value, ((rootHeight - size.toPx()) / 2).round().toPx().value),
+            Offset(
+                size.value.toFloat(),
+                ((rootHeight - size.value.toFloat()) / 2f).roundToInt().toFloat()
+            ),
             childPosition[1]
         )
 
         assertEquals(IntPxSize(size, size), childSize[2])
         assertEquals(
-            PxPosition((size.toPx() * 2).value, (rootHeight - size.toPx()).value),
+            Offset((size.value.toFloat() * 2), (rootHeight - size.value.toFloat())),
             childPosition[2])
     }
 
@@ -780,7 +783,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childSize = arrayOfNulls<IntPxSize>(4)
-        val childPosition = arrayOfNulls<PxPosition>(4)
+        val childPosition = arrayOfNulls<Offset>(4)
         show {
             Row(Modifier.fillMaxHeight()) {
                     BaselineTestLayout(
@@ -834,23 +837,26 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
         assertEquals(
-            PxPosition(size.toPx().value, (baseline1 - (size.toPx() / 2).round()).toPx().value),
+            Offset(
+                size.value.toFloat(),
+                (baseline1.value.toFloat() - (size.value.toFloat() / 2).roundToInt())
+            ),
             childPosition[1]
         )
 
         assertEquals(IntPxSize(size, size), childSize[2])
         assertEquals(
-            PxPosition((size.toPx() * 2).value, (baseline1 - baseline2).toPx().value),
+            Offset((size.value.toFloat() * 2), (baseline1 - baseline2).value.toFloat()),
             childPosition[2]
         )
 
         assertEquals(IntPxSize(size, size), childSize[3])
         assertEquals(
-            PxPosition((size.toPx() * 3).value, 0f),
+            Offset((size.value.toFloat() * 3), 0f),
             childPosition[3]
         )
     }
@@ -864,7 +870,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Row(Modifier.fillMaxHeight()) {
                 BaselineTestLayout(
@@ -895,11 +901,11 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(size, childSize[1]!!.height)
         assertEquals(
-            PxPosition(size.toPx().value, (baseline - size / 2).toPx().value),
+            Offset(size.value.toFloat(), (baseline - size / 2).value.toFloat()),
             childPosition[1]
         )
     }
@@ -913,7 +919,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOf(IntPxSize(-1.ipx, -1.ipx), IntPxSize(-1.ipx, -1.ipx))
-        val childPosition = arrayOf(PxPosition(-1f, -1f), PxPosition(-1f, -1f))
+        val childPosition = arrayOf(Offset(-1f, -1f), Offset(-1f, -1f))
         show {
             Column {
                     Container(
@@ -922,7 +928,7 @@
                         modifier = Modifier.fillMaxWidth()
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[0] = coordinates.size
-                                childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             }
                     ) {
@@ -934,7 +940,7 @@
                         modifier = Modifier.fillMaxWidth()
                             .onPositioned { coordinates: LayoutCoordinates ->
                                 childSize[1] = coordinates.size
-                                childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                                childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                                 drawLatch.countDown()
                             }
                     ) {
@@ -951,8 +957,8 @@
             IntPxSize(root.width.ipx, (sizeDp * 2).toIntPx()),
             childSize[1]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, size.toPx().value), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, size.value.toFloat()), childPosition[1])
     }
 
     @Test
@@ -962,7 +968,7 @@
 
         val drawLatch = CountDownLatch(3)
         val childSize = arrayOfNulls<IntPxSize>(3)
-        val childPosition = arrayOfNulls<PxPosition>(3)
+        val childPosition = arrayOfNulls<Offset>(3)
         show {
             Column(Modifier.fillMaxWidth()) {
                     Container(
@@ -1004,23 +1010,23 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
         assertEquals(
-            PxPosition(
-                ((rootWidth - size.toPx()) / 2).round().toPx().value,
-                size.toPx().value
+            Offset(
+                ((rootWidth - size.value.toFloat()) / 2).roundToInt().toFloat(),
+                size.value.toFloat()
             ),
             childPosition[1]
         )
 
         assertEquals(IntPxSize(size, size), childSize[2])
         assertEquals(
-            PxPosition((rootWidth - size.toPx()).value, size.toPx().value * 2),
+            Offset((rootWidth - size.value.toFloat()), size.value.toFloat() * 2),
             childPosition[2]
         )
     }
@@ -1032,7 +1038,7 @@
 
         val drawLatch = CountDownLatch(3)
         val childSize = arrayOfNulls<IntPxSize>(3)
-        val childPosition = arrayOfNulls<PxPosition>(3)
+        val childPosition = arrayOfNulls<Offset>(3)
         show {
             Column(Modifier.fillMaxWidth(), horizontalGravity = Alignment.CenterHorizontally) {
                 Container(
@@ -1073,23 +1079,23 @@
 
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
         assertEquals(
-            PxPosition(
-                ((rootWidth - size.toPx()) / 2).round().toPx().value,
-                size.toPx().value
+            Offset(
+                ((rootWidth - size.value.toFloat()) / 2).roundToInt().toFloat(),
+                size.value.toFloat()
             ),
             childPosition[1]
         )
 
         assertEquals(IntPxSize(size, size), childSize[2])
         assertEquals(
-            PxPosition((rootWidth - size.toPx()).value, size.toPx().value * 2),
+            Offset((rootWidth - size.value.toFloat()), size.value.toFloat() * 2),
             childPosition[2]
         )
     }
@@ -1103,7 +1109,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childSize = arrayOfNulls<IntPxSize>(4)
-        val childPosition = arrayOfNulls<PxPosition>(4)
+        val childPosition = arrayOfNulls<Offset>(4)
         show {
             Column(Modifier.fillMaxWidth()) {
                     Container(
@@ -1157,25 +1163,25 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(IntPxSize(size, size), childSize[1])
-        assertEquals(PxPosition(size.toPx().value, size.toPx().value), childPosition[1])
+        assertEquals(Offset(size.value.toFloat(), size.value.toFloat()), childPosition[1])
 
         assertEquals(IntPxSize(size, size), childSize[2])
         assertEquals(
-            PxPosition(
-                (size - firstBaseline1Dp.toIntPx()).toPx().value,
-                size.toPx().value * 2
+            Offset(
+                (size - firstBaseline1Dp.toIntPx()).value.toFloat(),
+                size.value.toFloat() * 2
             ),
             childPosition[2]
         )
 
         assertEquals(IntPxSize(size, size), childSize[3])
         assertEquals(
-            PxPosition(
-                (size - firstBaseline2Dp.toIntPx()).toPx().value,
-                size.toPx().value * 3
+            Offset(
+                (size - firstBaseline2Dp.toIntPx()).value.toFloat(),
+                size.value.toFloat() * 3
             ),
             childPosition[3]
         )
@@ -1190,7 +1196,7 @@
 
         val drawLatch = CountDownLatch(2)
         val childSize = arrayOfNulls<IntPxSize>(2)
-        val childPosition = arrayOfNulls<PxPosition>(2)
+        val childPosition = arrayOfNulls<Offset>(2)
         show {
             Column(Modifier.fillMaxWidth()) {
                 BaselineTestLayout(
@@ -1221,11 +1227,11 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(size, size), childSize[0])
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, 0f), childPosition[0])
 
         assertEquals(size, childSize[1]!!.width)
         assertEquals(
-            PxPosition((baseline - (size / 2)).toPx().value, size.toPx().value),
+            Offset((baseline - (size / 2)).value.toFloat(), size.value.toFloat()),
             childPosition[1]
         )
     }
@@ -2136,7 +2142,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2169,9 +2175,9 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(size.toPx().value, 0f), childPosition[1])
-        assertEquals(PxPosition(size.toPx().value * 2, 0f), childPosition[2])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(size.value.toFloat(), 0f), childPosition[1])
+        assertEquals(Offset(size.value.toFloat() * 2, 0f), childPosition[2])
     }
 
     @Test
@@ -2181,7 +2187,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2212,9 +2218,9 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        assertEquals(PxPosition((root.width.px - size.toPx() * 3).value, 0f), childPosition[0])
-        assertEquals(PxPosition((root.width.px - size.toPx() * 2).value, 0f), childPosition[1])
-        assertEquals(PxPosition((root.width.px - size.toPx()).value, 0f), childPosition[2])
+        assertEquals(Offset((root.width - size.value.toFloat() * 3), 0f), childPosition[0])
+        assertEquals(Offset((root.width - size.value.toFloat() * 2), 0f), childPosition[1])
+        assertEquals(Offset((root.width - size.value.toFloat()), 0f), childPosition[2])
     }
 
     @Test
@@ -2224,7 +2230,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2255,15 +2261,15 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val extraSpace = root.width.px.round() - size * 3
-        assertEquals(PxPosition((extraSpace / 2).toPx().value, 0f), childPosition[0])
+        val extraSpace = root.width - size.value * 3
+        assertEquals(Offset((extraSpace / 2f).roundToInt().toFloat(), 0f), childPosition[0])
         assertEquals(
-            PxPosition(((extraSpace / 2).toPx() + size.toPx()).value, 0f),
+            Offset(((extraSpace / 2f) + size.value.toFloat()).roundToInt().toFloat(), 0f),
             childPosition[1]
         )
         assertEquals(
-            PxPosition(
-                ((extraSpace / 2).toPx() + size.toPx() * 2).value,
+            Offset(
+                ((extraSpace / 2f) + size.value.toFloat() * 2).roundToInt().toFloat(),
                 0f
             ),
             childPosition[2]
@@ -2277,7 +2283,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2308,14 +2314,16 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.width.px - size.toPx() * 3) / 4
-        assertEquals(PxPosition(gap.round().toPx().value, 0f), childPosition[0])
+        val gap = (root.width - size.value.toFloat() * 3f) / 4f
         assertEquals(
-            PxPosition((size.toPx() + gap * 2).round().toPx().value, 0f),
+            Offset(gap.roundToInt().toFloat(), 0f), childPosition[0]
+        )
+        assertEquals(
+            Offset((size.value.toFloat() + gap * 2f).roundToInt().toFloat(), 0f),
             childPosition[1]
         )
         assertEquals(
-            PxPosition((size.toPx() * 2 + gap * 3).round().toPx().value, 0f),
+            Offset((size.value.toFloat() * 2f + gap * 3f).roundToInt().toFloat(), 0f),
             childPosition[2]
         )
     }
@@ -2327,7 +2335,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2358,11 +2366,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.width.px - size.toPx() * 3) / 2
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition((gap + size.toPx()).round().toPx().value, 0f), childPosition[1])
+        val gap = (root.width - size.value.toFloat() * 3) / 2
+        assertEquals(Offset(0f, 0f), childPosition[0])
         assertEquals(
-            PxPosition((gap * 2 + size.toPx() * 2).round().toPx().value, 0f),
+            Offset((gap + size.value.toFloat()).roundToInt().toFloat(), 0f),
+            childPosition[1]
+        )
+        assertEquals(
+            Offset((gap * 2 + size.value.toFloat() * 2).roundToInt().toFloat(), 0f),
             childPosition[2]
         )
     }
@@ -2374,7 +2385,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2408,14 +2419,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.width.px.round() - size * 3) / 3
-        assertEquals(PxPosition((gap / 2).toPx().value, 0f), childPosition[0])
+        val gap = (root.width.toFloat() - size.value * 3) / 3
+        assertEquals(Offset((gap / 2f).roundToInt().toFloat(), 0f), childPosition[0])
         assertEquals(
-            PxPosition(((gap * 3 / 2).toPx() + size.toPx()).value, 0f),
+            Offset(((gap * 3 / 2) + size.value.toFloat()).roundToInt().toFloat(), 0f),
             childPosition[1]
         )
         assertEquals(
-            PxPosition(((gap * 5 / 2).toPx() + size.toPx() * 2).value, 0f),
+            Offset(((gap * 5 / 2) + size.value.toFloat() * 2).roundToInt().toFloat(), 0f),
             childPosition[2]
         )
     }
@@ -2427,7 +2438,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition.Origin, PxPosition.Origin, PxPosition.Origin
+            Offset.Zero, Offset.Zero, Offset.Zero
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2458,14 +2469,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val step = (root.width.px - size.toPx() * 3) / 3
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
+        val step = (root.width - size.value.toFloat() * 3) / 3
+        assertEquals(Offset(0f, 0f), childPosition[0])
         assertEquals(
-            PxPosition((step + size.toPx()).round().toPx().value, 0f),
+            Offset((step + size.value.toFloat()).roundToInt().toFloat(), 0f),
             childPosition[1]
         )
         assertEquals(
-            PxPosition((step * 3 + size.toPx() * 2).round().toPx().value, 0f),
+            Offset((step * 3 + size.value.toFloat() * 2).roundToInt().toFloat(), 0f),
             childPosition[2]
         )
     }
@@ -2479,7 +2490,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2510,9 +2521,9 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, size.toPx().value), childPosition[1])
-        assertEquals(PxPosition(0f, size.toPx().value * 2), childPosition[2])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, size.value.toFloat()), childPosition[1])
+        assertEquals(Offset(0f, size.value.toFloat() * 2), childPosition[2])
     }
 
     @Test
@@ -2522,7 +2533,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2553,9 +2564,9 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        assertEquals(PxPosition(0f, (root.height.px - size.toPx() * 3).value), childPosition[0])
-        assertEquals(PxPosition(0f, (root.height.px - size.toPx() * 2).value), childPosition[1])
-        assertEquals(PxPosition(0f, (root.height.px - size.toPx()).value), childPosition[2])
+        assertEquals(Offset(0f, (root.height - size.value.toFloat() * 3)), childPosition[0])
+        assertEquals(Offset(0f, (root.height - size.value.toFloat() * 2)), childPosition[1])
+        assertEquals(Offset(0f, (root.height - size.value.toFloat())), childPosition[2])
     }
 
     @Test
@@ -2565,7 +2576,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2596,19 +2607,19 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val extraSpace = root.height.px.round() - size * 3
+        val extraSpace = root.height - size.value * 3f
         assertEquals(
-            PxPosition(0f, (extraSpace / 2).toPx().value),
+            Offset(0f, (extraSpace / 2).roundToInt().toFloat()),
             childPosition[0]
         )
         assertEquals(
-            PxPosition(0f, ((extraSpace / 2).toPx() + size.toPx()).value),
+            Offset(0f, ((extraSpace / 2) + size.value.toFloat()).roundToInt().toFloat()),
             childPosition[1]
         )
         assertEquals(
-            PxPosition(
+            Offset(
                 0f,
-                ((extraSpace / 2).toPx() + size.toPx() * 2).value
+                ((extraSpace / 2) + size.value.toFloat() * 2f).roundToInt().toFloat()
             ),
             childPosition[2]
         )
@@ -2621,7 +2632,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2652,23 +2663,26 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.height.px - size.toPx() * 3) / 4
-        assertEquals(PxPosition(0f, gap.round().toPx().value), childPosition[0])
-        assertEquals(PxPosition(0f, (size.toPx() + gap * 2).round().toPx().value), childPosition[1])
+        val gap = (root.height - size.value.toFloat() * 3) / 4
+        assertEquals(Offset(0f, gap.roundToInt().toFloat()), childPosition[0])
         assertEquals(
-            PxPosition(0f, (size.toPx() * 2 + gap * 3).round().toPx().value),
+            Offset(0f, (size.value.toFloat() + gap * 2).roundToInt().toFloat()),
+            childPosition[1]
+        )
+        assertEquals(
+            Offset(0f, (size.value.toFloat() * 2 + gap * 3f).roundToInt().toFloat()),
             childPosition[2]
         )
     }
 
     private fun calculateChildPositions(
-        childPosition: Array<PxPosition>,
+        childPosition: Array<Offset>,
         parentLayoutCoordinates: LayoutCoordinates?,
         childLayoutCoordinates: Array<LayoutCoordinates?>
     ) {
         for (i in childPosition.indices) {
             childPosition[i] = parentLayoutCoordinates!!
-                .childToLocal(childLayoutCoordinates[i]!!, PxPosition(0f, 0f))
+                .childToLocal(childLayoutCoordinates[i]!!, Offset(0f, 0f))
         }
     }
 
@@ -2679,7 +2693,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2710,11 +2724,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.height.px - size.toPx() * 3) / 2
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, (gap + size.toPx()).round().toPx().value), childPosition[1])
+        val gap = (root.height - size.value.toFloat() * 3f) / 2f
+        assertEquals(Offset(0f, 0f), childPosition[0])
         assertEquals(
-            PxPosition(0f, (gap * 2 + size.toPx() * 2).round().toPx().value),
+            Offset(0f, (gap + size.value.toFloat()).roundToInt().toFloat()),
+            childPosition[1]
+        )
+        assertEquals(
+            Offset(0f, (gap * 2 + size.value.toFloat() * 2).roundToInt().toFloat()),
             childPosition[2]
         )
     }
@@ -2726,7 +2743,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition(-1f, -1f), PxPosition(-1f, -1f), PxPosition(-1f, -1f)
+            Offset(-1f, -1f), Offset(-1f, -1f), Offset(-1f, -1f)
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2757,14 +2774,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val gap = (root.height.px - size.toPx() * 3) / 3
-        assertEquals(PxPosition(0f, (gap / 2).round().toPx().value), childPosition[0])
+        val gap = (root.height - size.value.toFloat() * 3f) / 3f
+        assertEquals(Offset(0f, (gap / 2f).roundToInt().toFloat()), childPosition[0])
         assertEquals(
-            PxPosition(0f, ((gap * 3 / 2) + size.toPx()).round().toPx().value),
+            Offset(0f, ((gap * 3f / 2f) + size.value.toFloat()).roundToInt().toFloat()),
             childPosition[1]
         )
         assertEquals(
-            PxPosition(0f, ((gap * 5 / 2) + size.toPx() * 2).round().toPx().value),
+            Offset(0f, ((gap * 5f / 2f) + size.value.toFloat() * 2f).roundToInt().toFloat()),
             childPosition[2]
         )
     }
@@ -2776,7 +2793,7 @@
 
         val drawLatch = CountDownLatch(4)
         val childPosition = arrayOf(
-            PxPosition.Origin, PxPosition.Origin, PxPosition.Origin
+            Offset.Zero, Offset.Zero, Offset.Zero
         )
         val childLayoutCoordinates = arrayOfNulls<LayoutCoordinates?>(childPosition.size)
         var parentLayoutCoordinates: LayoutCoordinates? = null
@@ -2807,11 +2824,14 @@
         val root = findOwnerView()
         waitForDraw(root)
 
-        val step = (root.height.px - size.toPx() * 3) / 3
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, (step + size.toPx()).round().toPx().value), childPosition[1])
+        val step = (root.height - size.value.toFloat() * 3f) / 3f
+        assertEquals(Offset(0f, 0f), childPosition[0])
         assertEquals(
-            PxPosition(0f, (step * 3 + size.toPx() * 2).round().toPx().value),
+            Offset(0f, (step + size.value.toFloat()).roundToInt().toFloat()),
+            childPosition[1]
+        )
+        assertEquals(
+            Offset(0f, (step * 3 + size.value.toFloat() * 2).roundToInt().toFloat()),
             childPosition[2]
         )
     }
@@ -3457,7 +3477,7 @@
     fun testRelativeToSiblingsModifiersChain_leftMostWins() = with(density) {
         val positionedLatch = CountDownLatch(1)
         val containerSize = Ref<IntPxSize>()
-        val containerPosition = Ref<PxPosition>()
+        val containerPosition = Ref<Offset>()
         val size = 40.dp
 
         show {
@@ -3486,7 +3506,7 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertNotNull(containerSize)
-        assertEquals(PxPosition(size.toPx(), size.toPx()), containerPosition.value)
+        assertEquals(Offset(size.toPx(), size.toPx()), containerPosition.value)
     }
     // endregion
 
@@ -3497,12 +3517,12 @@
         val size = sizeDp.toIntPx()
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Row(Modifier.fillMaxWidth().rtl) {
                 Container(
                     Modifier.preferredSize(sizeDp).onPositioned { coordinates: LayoutCoordinates ->
-                        childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                        childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                         drawLatch.countDown()
                     }
                 ) {
@@ -3511,7 +3531,7 @@
                 Container(
                     Modifier.preferredSize(sizeDp * 2)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3522,11 +3542,11 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
-        assertEquals(PxPosition((rootWidth - size.toPx()).value, 0f), childPosition[0])
+        assertEquals(Offset((rootWidth - size.value.toFloat()), 0f), childPosition[0])
         assertEquals(
-            PxPosition((rootWidth - (sizeDp.toPx() * 3).roundToInt().px).value, 0f),
+            Offset((rootWidth - (sizeDp.toPx() * 3f).roundToInt()).toFloat(), 0f),
             childPosition[1]
         )
     }
@@ -3536,7 +3556,7 @@
         val sizeDp = 35.dp
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Row(
                 Modifier.fillMaxWidth().rtl,
@@ -3544,7 +3564,7 @@
             ) {
                 Container(
                     Modifier.preferredSize(sizeDp).onPositioned { coordinates: LayoutCoordinates ->
-                        childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                        childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                         drawLatch.countDown()
                     }
                 ) {
@@ -3553,7 +3573,7 @@
                 Container(
                     Modifier.preferredSize(sizeDp * 2)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3564,13 +3584,13 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(
-            PxPosition(
+            Offset(
                 (sizeDp.toPx() * 2).roundToInt().toFloat(),
                 0f
             ),
             childPosition[0]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[1])
     }
 
     @Test
@@ -3578,7 +3598,7 @@
         val sizeDp = 35.dp
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Row(
                 Modifier.fillMaxWidth().rtl,
@@ -3588,7 +3608,7 @@
                     width = sizeDp,
                     height = sizeDp,
                     modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
-                        childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                        childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                         drawLatch.countDown()
                     }
                 ) {
@@ -3598,7 +3618,7 @@
                     width = (sizeDp * 2),
                     height = (sizeDp * 2),
                     modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
-                        childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                        childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                         drawLatch.countDown()
                     }
                 ) {
@@ -3611,10 +3631,10 @@
         waitForDraw(root)
 
         assertEquals(
-            PxPosition((sizeDp.toPx() * 2).roundToInt().toFloat(), 0f),
+            Offset((sizeDp.toPx() * 2).roundToInt().toFloat(), 0f),
             childPosition[0]
         )
-        assertEquals(PxPosition(0f, 0f), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[1])
     }
 
     @Test
@@ -3623,12 +3643,12 @@
         val size = sizeDp.toIntPx()
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Column(Modifier.fillMaxWidth().rtl) {
                 Container(
                     Modifier.preferredSize(sizeDp).onPositioned { coordinates: LayoutCoordinates ->
-                        childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                        childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                         drawLatch.countDown()
                     }
                 ) {
@@ -3637,7 +3657,7 @@
                 Container(
                     Modifier.preferredSize(sizeDp * 2)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3648,13 +3668,13 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
-        assertEquals(PxPosition((rootWidth - size.toPx()).value, 0f), childPosition[0])
+        assertEquals(Offset((rootWidth - size.value.toFloat()), 0f), childPosition[0])
         assertEquals(
-            PxPosition(
-                (rootWidth.value - (sizeDp * 2).toPx()).roundToInt().toFloat(),
-                size.toPx().value
+            Offset(
+                (rootWidth - (sizeDp * 2f).toPx()).roundToInt().toFloat(),
+                size.value.toFloat()
             ),
             childPosition[1]
         )
@@ -3666,14 +3686,14 @@
         val size = sizeDp.toIntPx()
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Column(Modifier.fillMaxWidth().rtl) {
                 Container(
                     Modifier.preferredSize(sizeDp)
                         .gravity(Alignment.End)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3683,7 +3703,7 @@
                     Modifier.preferredSize(sizeDp * 2)
                         .gravity(Alignment.End)
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3693,8 +3713,8 @@
 
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
 
-        assertEquals(PxPosition(0f, 0f), childPosition[0])
-        assertEquals(PxPosition(0f, size.toPx().value), childPosition[1])
+        assertEquals(Offset(0f, 0f), childPosition[0])
+        assertEquals(Offset(0f, size.value.toFloat()), childPosition[1])
     }
 
     @Test
@@ -3703,14 +3723,14 @@
         val size = sizeDp.toIntPx()
 
         val drawLatch = CountDownLatch(2)
-        val childPosition = arrayOf(PxPosition.Origin, PxPosition.Origin)
+        val childPosition = arrayOf(Offset.Zero, Offset.Zero)
         show {
             Column(Modifier.fillMaxWidth().rtl) {
                 Container(
                     Modifier.preferredSize(sizeDp)
                         .alignWithSiblings { it.width }
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[0] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[0] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3720,7 +3740,7 @@
                     Modifier.preferredSize(sizeDp)
                         .alignWithSiblings { it.width / 2 }
                         .onPositioned { coordinates: LayoutCoordinates ->
-                            childPosition[1] = coordinates.localToGlobal(PxPosition(0f, 0f))
+                            childPosition[1] = coordinates.localToGlobal(Offset(0f, 0f))
                             drawLatch.countDown()
                         }
                 ) {
@@ -3731,11 +3751,12 @@
         assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
         val root = findOwnerView()
         waitForDraw(root)
-        val rootWidth = root.width.px
+        val rootWidth = root.width
 
-        assertEquals(PxPosition((rootWidth - size.toPx()).value, 0f), childPosition[0])
+        assertEquals(Offset((rootWidth - size.value.toFloat()), 0f), childPosition[0])
         assertEquals(
-            PxPosition((rootWidth - size.toPx() * 1.5f).round().toPx().value, size.toPx().value),
+            Offset((rootWidth - size.value.toFloat() * 1.5f).roundToInt().toFloat(),
+                size.value.toFloat()),
             childPosition[1]
         )
     }
diff --git a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/StackTest.kt b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/StackTest.kt
index b938841..f90759d 100644
--- a/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/StackTest.kt
+++ b/ui/ui-layout/src/androidTest/java/androidx/ui/layout/test/StackTest.kt
@@ -33,10 +33,9 @@
 import androidx.ui.layout.wrapContentSize
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.toPx
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
@@ -44,6 +43,7 @@
 import org.junit.runners.JUnit4
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
 
 @SmallTest
 @RunWith(JUnit4::class)
@@ -56,9 +56,9 @@
         val positionedLatch = CountDownLatch(3)
         val stackSize = Ref<IntPxSize>()
         val alignedChildSize = Ref<IntPxSize>()
-        val alignedChildPosition = Ref<PxPosition>()
+        val alignedChildPosition = Ref<Offset>()
         val positionedChildSize = Ref<IntPxSize>()
-        val positionedChildPosition = Ref<PxPosition>()
+        val positionedChildPosition = Ref<Offset>()
         show {
             Container(alignment = Alignment.TopStart) {
                 Stack {
@@ -91,9 +91,12 @@
 
         assertEquals(IntPxSize(size, size), stackSize.value)
         assertEquals(IntPxSize(size, size), alignedChildSize.value)
-        assertEquals(PxPosition(0f, 0f), alignedChildPosition.value)
+        assertEquals(Offset(0f, 0f), alignedChildPosition.value)
         assertEquals(IntPxSize(30.dp.toIntPx(), 30.dp.toIntPx()), positionedChildSize.value)
-        assertEquals(PxPosition(10.dp.toIntPx(), 10.dp.toIntPx()), positionedChildPosition.value)
+        assertEquals(
+            Offset(10.dp.toPx().roundToInt().toFloat(), 10.dp.toPx().roundToInt().toFloat()),
+            positionedChildPosition.value
+        )
     }
 
     @Test
@@ -106,7 +109,7 @@
         val positionedLatch = CountDownLatch(3)
         val stackSize = Ref<IntPxSize>()
         val childSize = arrayOf(Ref<IntPxSize>(), Ref<IntPxSize>())
-        val childPosition = arrayOf(Ref<PxPosition>(), Ref<PxPosition>())
+        val childPosition = arrayOf(Ref<Offset>(), Ref<Offset>())
         show {
             Container(alignment = Alignment.TopStart) {
                 Stack(Modifier.onPositioned { coordinates: LayoutCoordinates ->
@@ -142,9 +145,12 @@
 
         assertEquals(IntPxSize(doubleSize, doubleSize), stackSize.value)
         assertEquals(IntPxSize(size, size), childSize[0].value)
-        assertEquals(PxPosition(size, size), childPosition[0].value)
+        assertEquals(
+            Offset(size.value.toFloat(), size.value.toFloat()),
+            childPosition[0].value
+        )
         assertEquals(IntPxSize(doubleSize, doubleSize), childSize[1].value)
-        assertEquals(PxPosition(0f, 0f), childPosition[1].value)
+        assertEquals(Offset(0f, 0f), childPosition[1].value)
     }
 
     @Test
@@ -158,7 +164,7 @@
         val positionedLatch = CountDownLatch(6)
         val stackSize = Ref<IntPxSize>()
         val childSize = Array(5) { Ref<IntPxSize>() }
-        val childPosition = Array(5) { Ref<PxPosition>() }
+        val childPosition = Array(5) { Ref<Offset>() }
         show {
             Container(alignment = Alignment.TopStart) {
                 Stack(Modifier.onPositioned { coordinates: LayoutCoordinates ->
@@ -214,15 +220,15 @@
 
         assertEquals(IntPxSize(size, size), stackSize.value)
         assertEquals(IntPxSize(size, size), childSize[0].value)
-        assertEquals(PxPosition(0f, 0f), childPosition[0].value)
+        assertEquals(Offset(0f, 0f), childPosition[0].value)
         assertEquals(IntPxSize(size - inset, size - inset), childSize[1].value)
-        assertEquals(PxPosition(inset, inset), childPosition[1].value)
+        assertEquals(Offset(inset.value.toFloat(), inset.value.toFloat()), childPosition[1].value)
         assertEquals(IntPxSize(size - inset, size - inset), childSize[2].value)
-        assertEquals(PxPosition(0f, 0f), childPosition[2].value)
+        assertEquals(Offset(0f, 0f), childPosition[2].value)
         assertEquals(IntPxSize(size - inset * 2, size), childSize[3].value)
-        assertEquals(PxPosition(inset, 0.ipx), childPosition[3].value)
+        assertEquals(Offset(inset.value.toFloat(), 0f), childPosition[3].value)
         assertEquals(IntPxSize(size, size - inset * 2), childSize[4].value)
-        assertEquals(PxPosition(0.ipx, inset), childPosition[4].value)
+        assertEquals(Offset(0f, inset.value.toFloat()), childPosition[4].value)
     }
 
     @Test
@@ -235,7 +241,7 @@
         val positionedLatch = CountDownLatch(10)
         val stackSize = Ref<IntPxSize>()
         val childSize = Array(9) { Ref<IntPxSize>() }
-        val childPosition = Array(9) { Ref<PxPosition>() }
+        val childPosition = Array(9) { Ref<Offset>() }
         show {
             Stack(Modifier.wrapContentSize(Alignment.TopStart)) {
                 Stack(
@@ -306,21 +312,30 @@
         assertTrue(positionedLatch.await(1, TimeUnit.SECONDS))
 
         assertEquals(IntPxSize(tripleSize, tripleSize), stackSize.value)
-        assertEquals(PxPosition((size * 2).value.toFloat(), 0f), childPosition[0].value)
-        assertEquals(PxPosition(size, 0.ipx), childPosition[1].value)
-        assertEquals(PxPosition(0.ipx, 0.ipx), childPosition[2].value)
-        assertEquals(PxPosition((size * 2).toPx().value, size.toPx().value), childPosition[3].value)
-        assertEquals(PxPosition(size, size), childPosition[4].value)
-        assertEquals(PxPosition(0.ipx, size), childPosition[5].value)
+        assertEquals(Offset((size * 2).value.toFloat(), 0f), childPosition[0].value)
+        assertEquals(Offset(size.value.toFloat(), 0f), childPosition[1].value)
+        assertEquals(Offset(0f, 0f), childPosition[2].value)
         assertEquals(
-            PxPosition(
-                (size * 2).toPx().value,
-                (size * 2).toPx().value
+            Offset(
+                (size * 2).value.toFloat(),
+                size.value.toFloat()
+            ),
+            childPosition[3].value
+        )
+        assertEquals(Offset(size.value.toFloat(), size.value.toFloat()), childPosition[4].value)
+        assertEquals(Offset(0f, size.value.toFloat()), childPosition[5].value)
+        assertEquals(
+            Offset(
+                (size * 2).value.toFloat(),
+                (size * 2).value.toFloat()
             ),
             childPosition[6].value
         )
-        assertEquals(PxPosition(size, size * 2), childPosition[7].value)
-        assertEquals(PxPosition(0.ipx, size * 2), childPosition[8].value)
+        assertEquals(
+            Offset(size.value.toFloat(), (size * 2).value.toFloat()),
+            childPosition[7].value
+        )
+        assertEquals(Offset(0f, (size * 2).value.toFloat()), childPosition[8].value)
     }
 
     @Test
@@ -333,7 +348,7 @@
         val positionedLatch = CountDownLatch(3)
         val stackSize = Ref<IntPxSize>()
         val childSize = Array(2) { Ref<IntPxSize>() }
-        val childPosition = Array(2) { Ref<PxPosition>() }
+        val childPosition = Array(2) { Ref<Offset>() }
         show {
             Container(alignment = Alignment.TopStart) {
                 Container(
@@ -365,9 +380,15 @@
 
         assertEquals(IntPxSize(size, size), stackSize.value)
         assertEquals(IntPxSize(size, size), childSize[0].value)
-        assertEquals(PxPosition(0f, 0f), childPosition[0].value)
+        assertEquals(Offset(0f, 0f), childPosition[0].value)
         assertEquals(IntPxSize(halfSize, halfSize), childSize[1].value)
-        assertEquals(PxPosition(size - halfSize, size - halfSize), childPosition[1].value)
+        assertEquals(
+            Offset(
+                (size - halfSize).value.toFloat(),
+                (size - halfSize).value.toFloat()
+            ),
+            childPosition[1].value
+        )
     }
 
     @Test
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/Column.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/Column.kt
index 47db576..f249885 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/Column.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/Column.kt
@@ -71,7 +71,7 @@
         orientation = LayoutOrientation.Vertical,
         modifier = modifier,
         arrangement = verticalArrangement,
-        crossAxisAlignment = horizontalGravity,
+        crossAxisAlignment = CrossAxisAlignment.horizontal(horizontalGravity),
         crossAxisSize = SizeMode.Wrap,
         children = { ColumnScope.children() }
     )
@@ -90,7 +90,7 @@
      * @sample androidx.ui.layout.samples.SimpleGravityInColumn
      */
     @Stable
-    fun Modifier.gravity(align: Alignment.Horizontal) = this + GravityModifier(align)
+    fun Modifier.gravity(align: Alignment.Horizontal) = this + HorizontalGravityModifier(align)
 
     /**
      * Position the element horizontally such that its [alignmentLine] aligns with sibling elements
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt
index 6dcef13..85ec8c0 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/ConstraintLayout.kt
@@ -20,12 +20,12 @@
 
 import android.annotation.SuppressLint
 import android.util.Log
+import androidx.annotation.FloatRange
 import androidx.compose.Composable
 import androidx.compose.remember
 import androidx.constraintlayout.core.state.ConstraintReference
 import androidx.constraintlayout.core.state.Dimension.SPREAD_DIMENSION
 import androidx.constraintlayout.core.state.Dimension.WRAP_DIMENSION
-import androidx.constraintlayout.core.state.State
 import androidx.constraintlayout.core.state.helpers.BarrierReference
 import androidx.constraintlayout.core.widgets.ConstraintWidget
 import androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT
@@ -38,37 +38,69 @@
 import androidx.constraintlayout.core.widgets.analyzer.BasicMeasure
 import androidx.compose.Immutable
 import androidx.ui.core.Constraints
+import androidx.ui.core.LayoutDirection
 import androidx.ui.text.FirstBaseline
 import androidx.ui.core.Measurable
 import androidx.ui.core.MeasureScope
 import androidx.ui.core.Modifier
 import androidx.ui.core.MultiMeasureLayout
+import androidx.ui.core.ParentDataModifier
 import androidx.ui.core.Placeable
 import androidx.ui.core.hasFixedHeight
 import androidx.ui.core.hasFixedWidth
 import androidx.ui.core.tag
+import androidx.ui.layout.ConstraintSetBuilderScope.Companion.baselineAnchorFunction
+import androidx.ui.layout.ConstraintSetBuilderScope.Companion.horizontalAnchorFunctions
+import androidx.ui.layout.ConstraintSetBuilderScope.Companion.verticalAnchorFunctions
+import androidx.ui.layout.ConstraintSetBuilderScope.Companion.verticalAnchorIndexToFunctionIndex
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
+import androidx.ui.util.fastForEach
 
 /**
  * Layout that positions its children according to the constraints between them.
+ *
+ * Example usage:
+ * @sample androidx.ui.layout.samples.DemoInlineDSL
  */
-@ExperimentalLayout
 @Composable
 fun ConstraintLayout(
-    constraintSet: ConstraintSet,
     modifier: Modifier = Modifier,
-    children: @Composable () -> Unit
+    children: @Composable ConstraintLayoutScope.() -> Unit
 ) {
     val measurer = remember { Measurer() }
+    val scope = remember { ConstraintLayoutScope() }
+
     @Suppress("Deprecation")
-    MultiMeasureLayout(modifier = modifier, children = children) { measurables, constraints, _ ->
+    MultiMeasureLayout(modifier = modifier, children = {
+        scope.reset()
+        scope.children()
+    }) { measurables, constraints, layoutDirection ->
+        val constraintSet = object : ConstraintSet {
+            override fun applyTo(state: State, measurables: List<Measurable>) {
+                scope.applyTo(state)
+                measurables.fastForEach { measurable ->
+                    val parentData = measurable.parentData as? ConstraintLayoutParentData
+                    // Map the tag and the measurable, to be retrieved later during measurement.
+                    val givenTag = parentData?.ref?.tag
+                    state.map(givenTag ?: createTag(), measurable)
+                    // Run the constrainAs block of the child, to obtain its constraints.
+                    if (parentData != null) {
+                        val constrainScope = ConstrainScope(parentData.ref.tag)
+                        parentData.constrain(constrainScope)
+                        constrainScope.applyTo(state)
+                    }
+                }
+            }
+        }
+
         val layoutSize = measurer.performMeasure(
             constraints,
+            layoutDirection,
             constraintSet,
             measurables,
             this
@@ -80,16 +112,937 @@
 }
 
 /**
+ * Layout that positions its children according to the constraints between them.
+ *
+ * Example usage:
+ * @sample androidx.ui.layout.samples.DemoConstraintSet
+ */
+@Composable
+fun ConstraintLayout(
+    constraintSet: ConstraintSet,
+    modifier: Modifier = Modifier,
+    children: @Composable () -> Unit
+) {
+    val measurer = remember { Measurer() }
+    @Suppress("Deprecation")
+    MultiMeasureLayout(modifier, children) { measurables, constraints, layoutDirection ->
+        val layoutSize = measurer.performMeasure(
+            constraints,
+            layoutDirection,
+            constraintSet,
+            measurables,
+            this
+        )
+        layout(layoutSize.width, layoutSize.height) {
+            with(measurer) { performLayout() }
+        }
+    }
+}
+
+/**
+ * Represents a layout within a [ConstraintLayout].
+ */
+class ConstrainedLayoutReference(val tag: Any) {
+    /**
+     * The start anchor of this layout. Represents left in LTR layout direction, or right in RTL.
+     */
+    val start = ConstraintLayoutBaseScope.VerticalAnchor(tag, -2)
+
+    /**
+     * The left anchor of this layout.
+     */
+    val absoluteLeft = ConstraintLayoutBaseScope.VerticalAnchor(tag, 0)
+
+    /**
+     * The top anchor of this layout.
+     */
+    val top = ConstraintLayoutBaseScope.HorizontalAnchor(tag, 0)
+
+    /**
+     * The end anchor of this layout. Represents right in LTR layout direction, or left in RTL.
+     */
+    val end = ConstraintLayoutBaseScope.VerticalAnchor(tag, -1)
+
+    /**
+     * The right anchor of this layout.
+     */
+    val absoluteRight = ConstraintLayoutBaseScope.VerticalAnchor(tag, 1)
+
+    /**
+     * The bottom anchor of this layout.
+     */
+    val bottom = ConstraintLayoutBaseScope.HorizontalAnchor(tag, 1)
+
+    /**
+     * The baseline anchor of this layout.
+     */
+    val baseline = ConstraintLayoutBaseScope.BaselineAnchor(tag)
+}
+
+/**
+ * Common scope for [ConstraintLayoutScope] and [ConstraintSetScope], the content being shared
+ * between the inline DSL API and the ConstraintSet-based API.
+ */
+abstract class ConstraintLayoutBaseScope {
+    protected val tasks = mutableListOf<(State) -> Unit>()
+
+    fun applyTo(state: State) = tasks.forEach { it(state) }
+
+    fun reset() = tasks.clear()
+
+    /**
+     * Represents a vertical anchor (e.g. start/end of a layout, guideline) that layouts
+     * can link to in their `Modifier.constrainAs` or `constrain` blocks.
+     */
+    data class VerticalAnchor internal constructor(internal val tag: Any, internal val index: Int)
+
+    /**
+     * Represents a horizontal anchor (e.g. top/bottom of a layout, guideline) that layouts
+     * can link to in their `Modifier.constrainAs` or `constrain` blocks.
+     */
+    data class HorizontalAnchor internal constructor(internal val tag: Any, internal val index: Int)
+
+    /**
+     * Represents a horizontal anchor corresponding to the [FirstBaseline] of a layout that other
+     * layouts can link to in their `Modifier.constrainAs` or `constrain` blocks.
+     */
+    // TODO(popam): investigate if this can be just a HorizontalAnchor
+    data class BaselineAnchor internal constructor(internal val tag: Any)
+
+    /**
+     * Creates a guideline at a specific offset from the start of the [ConstraintLayout].
+     */
+    fun createGuidelineFromStart(offset: Dp): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.verticalGuideline(tag).apply {
+                if (state.layoutDirection == LayoutDirection.Ltr) start(offset) else end(offset)
+            }
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the left of the [ConstraintLayout].
+     */
+    fun createGuidelineFromAbsoluteLeft(offset: Dp): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.verticalGuideline(tag).apply { start(offset) } }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the start of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the start of the [ConstraintLayout], while 1f will
+     * correspond to the end.
+     */
+    fun createGuidelineFromStart(fraction: Float): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.verticalGuideline(tag).apply {
+                if (state.layoutDirection == LayoutDirection.Ltr) {
+                    percent(fraction)
+                } else {
+                    percent(1f - fraction)
+                }
+            }
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a width fraction from the left of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the left of the [ConstraintLayout], while 1f will
+     * correspond to the right.
+     */
+    // TODO(popam, b/157781990): this is not really percentage
+    fun createGuidelineFromAbsoluteLeft(fraction: Float): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.verticalGuideline(tag).apply { percent(fraction) } }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the end of the [ConstraintLayout].
+     */
+    fun createGuidelineFromEnd(offset: Dp): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.verticalGuideline(tag).apply {
+                if (state.layoutDirection == LayoutDirection.Ltr) end(offset) else start(offset)
+            }
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the right of the [ConstraintLayout].
+     */
+    fun createGuidelineFromAbsoluteRight(offset: Dp): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.verticalGuideline(tag).apply { end(offset) } }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a width percentage from the end of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the end of the [ConstraintLayout], while 1f will
+     * correspond to the start.
+     */
+    fun createGuidelineFromEnd(fraction: Float): VerticalAnchor {
+        return createGuidelineFromStart(1f - fraction)
+    }
+
+    /**
+     * Creates a guideline at a width percentage from the right of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the right of the [ConstraintLayout], while 1f will
+     * correspond to the left.
+     */
+    fun createGuidelineFromAbsoluteRight(fraction: Float): VerticalAnchor {
+        return createGuidelineFromAbsoluteLeft(1f - fraction)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the top of the [ConstraintLayout].
+     */
+    fun createGuidelineFromTop(offset: Dp): HorizontalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.horizontalGuideline(tag).apply { start(offset) } }
+        return HorizontalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a height percentage from the top of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the top of the [ConstraintLayout], while 1f will
+     * correspond to the bottom.
+     */
+    fun createGuidelineFromTop(fraction: Float): HorizontalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.horizontalGuideline(tag).apply { percent(fraction) } }
+        return HorizontalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a specific offset from the bottom of the [ConstraintLayout].
+     */
+    fun createGuidelineFromBottom(offset: Dp): HorizontalAnchor {
+        val tag = createTag()
+        tasks.add { state -> state.horizontalGuideline(tag).apply { end(offset) } }
+        return HorizontalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a guideline at a height percentage from the bottom of the [ConstraintLayout].
+     * A [fraction] of 0f will correspond to the bottom of the [ConstraintLayout], while 1f will
+     * correspond to the top.
+     */
+    fun createGuidelineFromBottom(fraction: Float): HorizontalAnchor {
+        return createGuidelineFromTop(1f - fraction)
+    }
+
+    /**
+     * Creates and returns a start barrier, containing the specified elements.
+     */
+    fun createStartBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            val direction = if (state.layoutDirection == LayoutDirection.Ltr) {
+                SolverDirection.LEFT
+            } else {
+                SolverDirection.RIGHT
+            }
+            state.barrier(tag, direction).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates and returns a left barrier, containing the specified elements.
+     */
+    fun createAbsoluteLeftBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.barrier(tag, SolverDirection.LEFT).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates and returns a top barrier, containing the specified elements.
+     */
+    fun createTopBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): HorizontalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.barrier(tag, SolverDirection.TOP).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return HorizontalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates and returns an end barrier, containing the specified elements.
+     */
+    fun createEndBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            val direction = if (state.layoutDirection == LayoutDirection.Ltr) {
+                SolverDirection.RIGHT
+            } else {
+                SolverDirection.LEFT
+            }
+            state.barrier(tag, direction).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates and returns a right barrier, containing the specified elements.
+     */
+    fun createAbsoluteRightBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): VerticalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.barrier(tag, SolverDirection.RIGHT).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return VerticalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates and returns a bottom barrier, containing the specified elements.
+     */
+    fun createBottomBarrier(
+        vararg elements: ConstrainedLayoutReference,
+        margin: Dp = 0.dp
+    ): HorizontalAnchor {
+        val tag = createTag()
+        tasks.add { state ->
+            state.barrier(tag, SolverDirection.BOTTOM).apply {
+                add(*(elements.map { it.tag }.toTypedArray()))
+            }.margin(state.convertDimension(margin))
+        }
+        return HorizontalAnchor(tag, 0)
+    }
+
+    /**
+     * Creates a horizontal chain including the referenced layouts.
+     */
+    // TODO(popam, b/157783937): this API should be improved
+    fun createHorizontalChain(
+        vararg elements: ConstrainedLayoutReference,
+        chainStyle: ChainStyle = ChainStyle.Spread
+    ) {
+        tasks.add { state ->
+            state.horizontalChain(*(elements.map { it.tag }.toTypedArray()))
+                .also { it.style(chainStyle.style) }
+                .apply()
+            if (chainStyle.bias != null) {
+                state.constraints(elements[0].tag).horizontalBias(chainStyle.bias)
+            }
+        }
+    }
+
+    /**
+     * Creates a vertical chain including the referenced layouts.
+     */
+    // TODO(popam, b/157783937): this API should be improved
+    fun createVerticalChain(
+        vararg elements: ConstrainedLayoutReference,
+        chainStyle: ChainStyle = ChainStyle.Spread
+    ) {
+        tasks.add { state ->
+            state.verticalChain(*(elements.map { it.tag }.toTypedArray()))
+                .also { it.style(chainStyle.style) }
+                .apply()
+            if (chainStyle.bias != null) {
+                state.constraints(elements[0].tag).verticalBias(chainStyle.bias)
+            }
+        }
+    }
+}
+
+/**
+ * Scope used by the inline DSL of [ConstraintLayout].
+ */
+@LayoutScopeMarker
+class ConstraintLayoutScope internal constructor() : ConstraintLayoutBaseScope() {
+    /**
+     * Creates one [ConstrainedLayoutReference], which needs to be assigned to a layout within the
+     * [ConstraintLayout] as part of [Modifier.constrainAs]. To create more references at the
+     * same time, see [createRefs].
+     */
+    fun createRef() = ConstrainedLayoutReference(createTag())
+
+    /**
+     * Convenient way to create multiple [ConstrainedLayoutReference]s, which need to be assigned
+     * to layouts within the [ConstraintLayout] as part of [Modifier.constrainAs]. To create just
+     * one reference, see [createRef].
+     */
+    fun createRefs() = ConstrainedLayoutReferences()
+
+    /**
+     * Convenience API for creating multiple [ConstrainedLayoutReference] via [createRefs].
+     */
+    inner class ConstrainedLayoutReferences internal constructor() {
+        operator fun component1() = createRef()
+        operator fun component2() = createRef()
+        operator fun component3() = createRef()
+        operator fun component4() = createRef()
+        operator fun component5() = createRef()
+        operator fun component6() = createRef()
+        operator fun component7() = createRef()
+        operator fun component8() = createRef()
+        operator fun component9() = createRef()
+        operator fun component10() = createRef()
+        operator fun component11() = createRef()
+        operator fun component12() = createRef()
+        operator fun component13() = createRef()
+        operator fun component14() = createRef()
+        operator fun component15() = createRef()
+        operator fun component16() = createRef()
+    }
+
+    /**
+     * [Modifier] that defines the constraints, as part of a [ConstraintLayout], of the layout
+     * element.
+     */
+    fun Modifier.constrainAs(
+        ref: ConstrainedLayoutReference,
+        constrainBlock: ConstrainScope.() -> Unit
+    ): Modifier {
+        // TODO(popam, b/157782492): make equals comparable modifiers here.
+        return this + object : ParentDataModifier {
+            override fun Density.modifyParentData(parentData: Any?) =
+                ConstraintLayoutParentData(ref, constrainBlock)
+        }
+    }
+}
+
+/**
+ * Scope used by the [ConstraintSet] DSL.
+ */
+@LayoutScopeMarker
+class ConstraintSetScope internal constructor() : ConstraintLayoutBaseScope() {
+    /**
+     * Creates one [ConstrainedLayoutReference] corresponding to the [ConstraintLayout]
+     * [tagged][Modifier.tag] with [tag].
+     */
+    fun createRefFor(tag: Any) = ConstrainedLayoutReference(tag)
+
+    /**
+     * Specifies the constraints associated to the layout tagged with [ref] via [Modifier.tag].
+     */
+    fun constrain(
+        ref: ConstrainedLayoutReference,
+        constrainBlock: ConstrainScope.() -> Unit
+    ) = ConstrainScope(ref.tag).apply {
+        constrainBlock()
+        this@ConstraintSetScope.tasks.addAll(this.tasks)
+    }
+}
+
+/**
+ * The style of a horizontal or vertical chain.
+ */
+class ChainStyle internal constructor(
+    internal val style: SolverChain,
+    internal val bias: Float? = null
+) {
+    companion object {
+        /**
+         * A chain style that evenly distributes the contained layouts.
+         */
+        val Spread = ChainStyle(SolverChain.SPREAD)
+
+        /**
+         * A chain style where the first and last layouts are affixed to the constraints
+         * on each end of the chain and the rest are evenly distributed.
+         */
+        val SpreadInside = ChainStyle(SolverChain.SPREAD_INSIDE)
+
+        /**
+         * A chain style where the contained layouts are packed together and placed to the
+         * center of the available space.
+         */
+        val Packed = Packed(0.5f)
+
+        /**
+         * A chain style where the contained layouts are packed together and placed in
+         * the available space according to a given [bias].
+         */
+        fun Packed(bias: Float) = ChainStyle(SolverChain.PACKED, bias)
+    }
+}
+
+/**
+ * Parent data provided by `Modifier.constrainAs`.
+ */
+private class ConstraintLayoutParentData(
+    val ref: ConstrainedLayoutReference,
+    val constrain: ConstrainScope.() -> Unit
+)
+
+/**
+ * Scope used by `Modifier.constrainAs`.
+ */
+@LayoutScopeMarker
+class ConstrainScope internal constructor(internal val tag: Any) {
+    internal val tasks = mutableListOf<(State) -> Unit>()
+    internal fun applyTo(state: State) = tasks.forEach { it(state) }
+
+    /**
+     * Reference to the [ConstraintLayout] itself, which can be used to specify constraints
+     * between itself and its children.
+     */
+    val parent = ConstrainedLayoutReference(SolverState.PARENT)
+
+    /**
+     * The start anchor of the layout - can be constrained using [VerticalAnchorable.linkTo].
+     */
+    val start = VerticalAnchorable(tag, -2)
+
+    /**
+     * The left anchor of the layout - can be constrained using [VerticalAnchorable.linkTo].
+     */
+    val absoluteLeft = VerticalAnchorable(tag, 0)
+
+    /**
+     * The top anchor of the layout - can be constrained using [HorizontalAnchorable.linkTo].
+     */
+    val top = HorizontalAnchorable(tag, 0)
+
+    /**
+     * The end anchor of the layout - can be constrained using [VerticalAnchorable.linkTo].
+     */
+    val end = VerticalAnchorable(tag, -1)
+
+    /**
+     * The right anchor of the layout - can be constrained using [VerticalAnchorable.linkTo].
+     */
+    val absoluteRight = VerticalAnchorable(tag, 1)
+
+    /**
+     * The bottom anchor of the layout - can be constrained using [HorizontalAnchorable.linkTo].
+     */
+    val bottom = HorizontalAnchorable(tag, 1)
+
+    /**
+     * The [FirstBaseline] of the layout - can be constrained using [BaselineAnchorable.linkTo].
+     */
+    val baseline = BaselineAnchorable(tag)
+
+    /**
+     * The width of the [ConstraintLayout] child.
+     */
+    var width: Dimension = Dimension.wrapContent
+        set(value) {
+            field = value
+            tasks.add { state ->
+                state.constraints(tag).width(
+                    (value as DimensionDescription).toSolverDimension(state)
+                )
+            }
+        }
+
+    /**
+     * The height of the [ConstraintLayout] child.
+     */
+    var height: Dimension = Dimension.wrapContent
+        set(value) {
+            field = value
+            tasks.add { state ->
+                state.constraints(tag).height(
+                    (value as DimensionDescription).toSolverDimension(state)
+                )
+            }
+        }
+
+    /**
+     * Represents a vertical side of a layout (i.e start and end) that can be anchored using
+     * [linkTo] in their `Modifier.constrainAs` blocks.
+     */
+    inner class VerticalAnchorable internal constructor(
+        internal val tag: Any,
+        internal val index: Int
+    ) {
+        /**
+         * Adds a link towards a [ConstraintLayoutBaseScope.VerticalAnchor].
+         */
+        // TODO(popam, b/158069248): add parameter for gone margin
+        fun linkTo(anchor: ConstraintLayoutBaseScope.VerticalAnchor, margin: Dp = 0.dp) {
+            tasks.add { state ->
+                with(state.constraints(tag)) {
+                    val layoutDirection = state.layoutDirection
+                    val index1 = verticalAnchorIndexToFunctionIndex(index, layoutDirection)
+                    val index2 = verticalAnchorIndexToFunctionIndex(anchor.index, layoutDirection)
+                    verticalAnchorFunctions[index1][index2]
+                        .invoke(this, anchor.tag)
+                        .margin(margin)
+                }
+            }
+        }
+    }
+
+    /**
+     * Represents a horizontal side of a layout (i.e top and bottom) that can be anchored using
+     * [linkTo] in their `Modifier.constrainAs` blocks.
+     */
+    inner class HorizontalAnchorable internal constructor(
+        internal val tag: Any,
+        internal val index: Int
+    ) {
+        /**
+         * Adds a link towards a [ConstraintLayoutBaseScope.HorizontalAnchor].
+         */
+        // TODO(popam, b/158069248): add parameter for gone margin
+        fun linkTo(anchor: ConstraintLayoutBaseScope.HorizontalAnchor, margin: Dp = 0.dp) {
+            tasks.add { state ->
+                with(state.constraints(tag)) {
+                    horizontalAnchorFunctions[index][anchor.index]
+                        .invoke(this, anchor.tag)
+                        .margin(margin)
+                }
+            }
+        }
+    }
+
+    /**
+     * Represents the [FirstBaseline] of a layout that can be anchored
+     * using [linkTo] in their `Modifier.constrainAs` blocks.
+     */
+    inner class BaselineAnchorable internal constructor(internal val tag: Any) {
+        /**
+         * Adds a link towards a [ConstraintLayoutBaseScope.BaselineAnchor].
+         */
+        // TODO(popam, b/158069248): add parameter for gone margin
+        fun linkTo(anchor: ConstraintLayoutBaseScope.BaselineAnchor, margin: Dp = 0.dp) {
+            tasks.add { state ->
+                with(state.constraints(tag)) {
+                    baselineAnchorFunction.invoke(this, anchor.tag).margin(margin)
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds both start and end links towards other [ConstraintLayoutBaseScope.HorizontalAnchor]s.
+     */
+    // TODO(popam, b/158069248): add parameter for gone margin
+    fun linkTo(
+        start: ConstraintLayoutBaseScope.VerticalAnchor,
+        end: ConstraintLayoutBaseScope.VerticalAnchor,
+        startMargin: Dp = 0.dp,
+        endMargin: Dp = 0.dp,
+        @FloatRange(from = 0.0, to = 1.0) bias: Float = 0.5f
+    ) {
+        this@ConstrainScope.start.linkTo(start, startMargin)
+        this@ConstrainScope.end.linkTo(end, endMargin)
+        tasks.add { state ->
+            state.constraints(tag).horizontalBias(bias)
+        }
+    }
+
+    /**
+     * Adds both top and bottom links towards other [ConstraintLayoutBaseScope.HorizontalAnchor]s.
+     */
+    // TODO(popam, b/158069248): add parameter for gone margin
+    fun linkTo(
+        top: ConstraintLayoutBaseScope.HorizontalAnchor,
+        bottom: ConstraintLayoutBaseScope.HorizontalAnchor,
+        topMargin: Dp = 0.dp,
+        bottomMargin: Dp = 0.dp,
+        @FloatRange(from = 0.0, to = 1.0) bias: Float = 0.5f
+    ) {
+        this@ConstrainScope.top.linkTo(top, topMargin)
+        this@ConstrainScope.bottom.linkTo(bottom, bottomMargin)
+        tasks.add { state ->
+            state.constraints(tag).verticalBias(bias)
+        }
+    }
+
+    /**
+     * Adds all start, top, end, bottom links towards
+     * other [ConstraintLayoutBaseScope.HorizontalAnchor]s.
+     */
+    // TODO(popam, b/158069248): add parameter for gone margin
+    fun linkTo(
+        start: ConstraintLayoutBaseScope.VerticalAnchor,
+        top: ConstraintLayoutBaseScope.HorizontalAnchor,
+        end: ConstraintLayoutBaseScope.VerticalAnchor,
+        bottom: ConstraintLayoutBaseScope.HorizontalAnchor,
+        startMargin: Dp = 0.dp,
+        topMargin: Dp = 0.dp,
+        endMargin: Dp = 0.dp,
+        bottomMargin: Dp = 0.dp,
+        @FloatRange(from = 0.0, to = 1.0) horizontalBias: Float = 0.5f,
+        @FloatRange(from = 0.0, to = 1.0) verticalBias: Float = 0.5f
+    ) {
+        linkTo(start, end, startMargin, endMargin, horizontalBias)
+        linkTo(top, bottom, topMargin, bottomMargin, verticalBias)
+    }
+
+    /**
+     * Adds all start, top, end, bottom links towards the corresponding anchors of [other].
+     * This will center the current layout inside or around (depending on size) [other].
+     */
+    fun centerTo(other: ConstrainedLayoutReference) {
+        linkTo(other.start, other.top, other.end, other.bottom)
+    }
+
+    /**
+     * Adds start and end links towards the corresponding anchors of [other].
+     * This will center horizontally the current layout inside or around (depending on size)
+     * [other].
+     */
+    fun centerHorizontallyTo(other: ConstrainedLayoutReference) {
+        linkTo(other.start, other.end)
+    }
+
+    /**
+     * Adds top and bottom links towards the corresponding anchors of [other].
+     * This will center vertically the current layout inside or around (depending on size)
+     * [other].
+     */
+    fun centerVerticallyTo(other: ConstrainedLayoutReference) {
+        linkTo(other.top, other.bottom)
+    }
+
+    /**
+     * Adds start and end links towards a vertical [anchor].
+     * This will center the current layout around the vertical [anchor].
+     */
+    fun centerAround(anchor: ConstraintLayoutBaseScope.VerticalAnchor) {
+        linkTo(anchor, anchor)
+    }
+
+    /**
+     * Adds top and bottom links towards a horizontal [anchor].
+     * This will center the current layout around the horizontal [anchor].
+     */
+    fun centerAround(anchor: ConstraintLayoutBaseScope.HorizontalAnchor) {
+        linkTo(anchor, anchor)
+    }
+}
+
+/**
+ * Convenience for creating tags corresponding to layout references that cannot be referred
+ * to from the outside of the scope (e.g. barriers, layout references in the modifier-based API,
+ * etc.).
+ */
+private fun createTag() = object : Any() {}
+
+/**
+ * Represents a dimension that can be assigned to the width or height of a [ConstraintLayout]
+ * [child][ConstrainedLayoutReference].
+ */
+// TODO(popam, b/157781841): It is unfortunate that this interface is top level in ui-layout.
+//  This will be ok if we move constraint layout to its own module or at least subpackage.
+interface Dimension {
+    /**
+     * A [Dimension] that can be assigned both min and max bounds.
+     */
+    interface Coercible : Dimension
+
+    /**
+     * A [Dimension] that can be assigned a min bound.
+     */
+    interface MinCoercible : Dimension
+
+    /**
+     * A [Dimension] that can be assigned a max bound.
+     */
+    interface MaxCoercible : Dimension
+
+    companion object {
+        /**
+         * Creates a [Dimension] representing a suggested dp size. The requested size will
+         * be respected unless the constraints in the [ConstraintSet] do not allow it. The min
+         * and max bounds will be respected regardless of the constraints in the [ConstraintSet].
+         * To make the value fixed (respected regardless the [ConstraintSet]), [value] should
+         * be used instead.
+         */
+        fun preferredValue(dp: Dp): Dimension.Coercible =
+            DimensionDescription { state -> SolverDimension.Suggested(state.convertDimension(dp)) }
+
+        /**
+         * Creates a [Dimension] representing a fixed dp size. The size will not change
+         * according to the constraints in the [ConstraintSet].
+         */
+        fun value(dp: Dp): Dimension =
+            DimensionDescription { state -> SolverDimension.Fixed(state.convertDimension(dp)) }
+
+        /**
+         * A [Dimension] with suggested wrap content behavior. The wrap content size
+         * will be respected unless the constraints in the [ConstraintSet] do not allow it.
+         * To make the value fixed (respected regardless the [ConstraintSet]), [wrapContent]
+         * should be used instead.
+         */
+        val preferredWrapContent: Dimension.Coercible
+            get() = DimensionDescription { SolverDimension.Suggested(WRAP_DIMENSION) }
+
+        /**
+         * A [Dimension] with fixed wrap content behavior. The size will not change
+         * according to the constraints in the [ConstraintSet].
+         */
+        val wrapContent: Dimension
+            get() = DimensionDescription { SolverDimension.Fixed(WRAP_DIMENSION) }
+
+        /**
+         * A [Dimension] that spreads to match constraints. Links should be specified from both
+         * sides corresponding to this dimension, in order for this to work.
+         */
+        val fillToConstraints: Dimension
+            get() = DimensionDescription { SolverDimension.Suggested(SPREAD_DIMENSION) }
+
+        /**
+         * A [Dimension] that is a percent of the parent in the corresponding direction.
+         */
+        fun percent(percent: Float): Dimension =
+            // TODO(popam, b/157880732): make this nicer when possible in future solver releases
+            DimensionDescription { SolverDimension.Percent(0, percent).suggested(0) }
+    }
+}
+
+/**
+ * Sets the lower bound of the current [Dimension] to be the wrap content size of the child.
+ */
+val Dimension.Coercible.atLeastWrapContent: Dimension.MaxCoercible
+    get() = (this as DimensionDescription).also { it.minSymbol = WRAP_DIMENSION }
+
+/**
+ * Sets the lower bound of the current [Dimension] to a fixed [dp] value.
+ */
+fun Dimension.Coercible.atLeast(dp: Dp): Dimension.MaxCoercible =
+    (this as DimensionDescription).also { it.min = dp }
+
+/**
+ * Sets the upper bound of the current [Dimension] to a fixed [dp] value.
+ */
+fun Dimension.Coercible.atMost(dp: Dp): Dimension.MinCoercible =
+    (this as DimensionDescription).also { it.max = dp }
+
+/**
+ * Sets the upper bound of the current [Dimension] to be the wrap content size of the child.
+ */
+val Dimension.Coercible.atMostWrapContent: Dimension.MinCoercible
+    get() = (this as DimensionDescription).also { it.maxSymbol = WRAP_DIMENSION }
+
+/**
+ * Sets the lower bound of the current [Dimension] to a fixed [dp] value.
+ */
+fun Dimension.MinCoercible.atLeastWrapContent(dp: Dp): Dimension =
+    (this as DimensionDescription).also { it.min = dp }
+
+/**
+ * Sets the lower bound of the current [Dimension] to be the wrap content size of the child.
+ */
+val Dimension.MinCoercible.atLeastWrapContent: Dimension
+    get() = (this as DimensionDescription).also { it.minSymbol = WRAP_DIMENSION }
+
+/**
+ * Sets the upper bound of the current [Dimension] to a fixed [dp] value.
+ */
+fun Dimension.MaxCoercible.atMost(dp: Dp): Dimension =
+    (this as DimensionDescription).also { it.max = dp }
+
+/**
+ * Sets the upper bound of the current [Dimension] to be the [Wrap] size of the child.
+ */
+val Dimension.MaxCoercible.atMostWrapContent: Dimension
+    get() = (this as DimensionDescription).also { it.maxSymbol = WRAP_DIMENSION }
+
+/**
+ * Describes a sizing behavior that can be applied to the width or height of a
+ * [ConstraintLayout] child. The content of this class should not be instantiated
+ * directly; helpers available in the [Dimension]'s companion object should be used.
+ */
+internal class DimensionDescription internal constructor(
+    private val baseDimension: (State) -> SolverDimension
+) : Dimension.Coercible, Dimension.MinCoercible, Dimension.MaxCoercible, Dimension {
+    var min: Dp? = null
+    var minSymbol: Any? = null
+    var max: Dp? = null
+    var maxSymbol: Any? = null
+    internal fun toSolverDimension(state: State) = baseDimension(state).also {
+        if (minSymbol != null) {
+            it.min(minSymbol)
+        } else if (min != null) {
+            it.min(state.convertDimension(min!!))
+        }
+        if (maxSymbol != null) {
+            it.max(maxSymbol)
+        } else if (max != null) {
+            it.max(state.convertDimension(max!!))
+        }
+    }
+}
+
+/**
  * Immutable description of the constraints used to layout the children of a [ConstraintLayout].
  */
 @Immutable
-data class ConstraintSet(internal val description: ConstraintSetBuilderScope.() -> Unit)
+interface ConstraintSet {
+    /**
+     * Applies the [ConstraintSet] to a state.
+     */
+    fun applyTo(state: State, measurables: List<Measurable>)
+}
+
+@Deprecated("This API for building ConstraintSets has been deprecated. " +
+        "Consider using the inline DSL API - see ConstraintLayoutDemo for an example," +
+        "or use ConstraintSet2 for building constraint sets.")
+fun ConstraintSet(description: ConstraintSetBuilderScope.() -> Unit) = object : ConstraintSet {
+    override fun applyTo(state: State, measurables: List<Measurable>) {
+        measurables.forEach { measurable ->
+            state.map((measurable.tag ?: createTag()), measurable)
+        }
+        description(ConstraintSetBuilderScope(state))
+    }
+}
+
+/**
+ * Creates a [ConstraintSet].
+ */
+fun ConstraintSet2(description: ConstraintSetScope.() -> Unit) = object : ConstraintSet {
+    override fun applyTo(state: State, measurables: List<Measurable>) {
+        measurables.forEach { measurable ->
+            state.map((measurable.tag ?: createTag()), measurable)
+        }
+        val scope = ConstraintSetScope()
+        scope.description()
+        scope.applyTo(state)
+    }
+}
 
 /**
  * Builder scope for a [ConstraintSet]. The scope should not be created directly - the
  * [ConstraintSet] class constructor should be used instead.
  */
 // TODO(popam): support RTL
+@Deprecated("This way of building ConstraintSets has been deprecated. " +
+        "Use ConstraintSet2 (and its implicit ConstraintSetScope) instead.")
 class ConstraintSetBuilderScope internal constructor(internal val state: State) {
     /**
      * Creates a reference corresponding to the constraint layout children with a specific tag,
@@ -102,7 +1055,7 @@
      * Reference to the [ConstraintLayout] itself, which can be used to specify constraints
      * between itself and its children.
      */
-    val parent = ConstrainedLayoutReference(State.PARENT)
+    val parent = ConstrainedLayoutReference(SolverState.PARENT)
 
     /**
      * Represents a dimension that can be assigned to the width or height of a [ConstraintLayout]
@@ -568,14 +1521,32 @@
      * The style of a horizontal or vertical chain.
      */
     class ChainStyle internal constructor(
-        internal val style: State.Chain,
+        internal val style: SolverChain,
         internal val bias: Float? = null
     ) {
         companion object {
-            val Spread = ChainStyle(State.Chain.SPREAD)
-            val SpreadInside = ChainStyle(State.Chain.SPREAD_INSIDE)
+            /**
+             * A chain style that evenly distributes the contained layouts.
+             */
+            val Spread = ChainStyle(SolverChain.SPREAD)
+
+            /**
+             * A chain style where the first and last layouts are affixed to the constraints
+             * on each end of the chain and the rest are evenly distributed.
+             */
+            val SpreadInside = ChainStyle(SolverChain.SPREAD_INSIDE)
+
+            /**
+             * A chain style where the contained layouts are packed together and placed to the
+             * center of the available space.
+             */
             val Packed = Packed(0.5f)
-            fun Packed(bias: Float) = ChainStyle(State.Chain.PACKED, bias)
+
+            /**
+             * A chain style where the contained layouts are packed together and placed in
+             * the available space according to a given [bias].
+             */
+            fun Packed(bias: Float) = ChainStyle(SolverChain.PACKED, bias)
         }
     }
 
@@ -583,7 +1554,7 @@
      * Creates a guideline at a specific offset from the left of the [ConstraintLayout].
      */
     fun createGuidelineFromLeft(offset: Dp): VerticalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.verticalGuideline(tag).apply { start(offset) }
         return VerticalAnchor.GuidelineAnchor(state, tag)
     }
@@ -592,7 +1563,7 @@
      * Creates a guideline at a width percentage from the left of the [ConstraintLayout].
      */
     fun createGuidelineFromLeft(percent: Float): VerticalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.verticalGuideline(tag).apply { percent(percent) }
         return VerticalAnchor.GuidelineAnchor(state, tag)
     }
@@ -601,7 +1572,7 @@
      * Creates a guideline at a specific offset from the right of the [ConstraintLayout].
      */
     fun createGuidelineFromRight(offset: Dp): VerticalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.verticalGuideline(tag).apply { end(offset) }
         return VerticalAnchor.GuidelineAnchor(state, tag)
     }
@@ -617,7 +1588,7 @@
      * Creates a guideline at a specific offset from the top of the [ConstraintLayout].
      */
     fun createGuidelineFromTop(offset: Dp): HorizontalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.horizontalGuideline(tag).apply { start(offset) }
         return HorizontalAnchor.GuidelineAnchor(state, tag)
     }
@@ -626,7 +1597,7 @@
      * Creates a guideline at a height percentage from the top of the [ConstraintLayout].
      */
     fun createGuidelineFromTop(percent: Float): HorizontalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.horizontalGuideline(tag).apply { percent(percent) }
         return HorizontalAnchor.GuidelineAnchor(state, tag)
     }
@@ -635,7 +1606,7 @@
      * Creates a guideline at a specific offset from the bottom of the [ConstraintLayout].
      */
     fun createGuidelineFromBottom(offset: Dp): HorizontalAnchor.GuidelineAnchor {
-        val tag = object : Any() {}
+        val tag = createTag()
         state.horizontalGuideline(tag).apply { end(offset) }
         return HorizontalAnchor.GuidelineAnchor(state, tag)
     }
@@ -653,8 +1624,8 @@
     fun createTopBarrier(
         vararg elements: ConstrainedLayoutReference
     ): HorizontalAnchor.BarrierAnchor {
-        val tag = object : Any() {}
-        val barrier = state.barrier(tag, State.Direction.TOP).apply {
+        val tag = createTag()
+        val barrier = state.barrier(tag, SolverDirection.TOP).apply {
             add(*(elements.map { it.tag }.toTypedArray()))
         }
         return HorizontalAnchor.BarrierAnchor(state, tag, barrier)
@@ -666,8 +1637,8 @@
     fun createBottomBarrier(
         vararg elements: ConstrainedLayoutReference
     ): HorizontalAnchor.BarrierAnchor {
-        val tag = object : Any() {}
-        val barrier = state.barrier(tag, State.Direction.BOTTOM).apply {
+        val tag = createTag()
+        val barrier = state.barrier(tag, SolverDirection.BOTTOM).apply {
             add(*(elements.map { it.tag }.toTypedArray()))
         }
         return HorizontalAnchor.BarrierAnchor(state, tag, barrier)
@@ -679,8 +1650,8 @@
     fun createLeftBarrier(
         vararg elements: ConstrainedLayoutReference
     ): VerticalAnchor.BarrierAnchor {
-        val tag = object : Any() {}
-        val barrier = state.barrier(tag, State.Direction.START).apply {
+        val tag = createTag()
+        val barrier = state.barrier(tag, SolverDirection.START).apply {
             add(*(elements.map { it.tag }.toTypedArray()))
         }
         return VerticalAnchor.BarrierAnchor(state, tag, barrier)
@@ -692,25 +1663,40 @@
     fun createRightBarrier(
         vararg elements: ConstrainedLayoutReference
     ): VerticalAnchor.BarrierAnchor {
-        val tag = object : Any() {}
-        val barrier = state.barrier(tag, State.Direction.END).apply {
+        val tag = createTag()
+        val barrier = state.barrier(tag, SolverDirection.END).apply {
             add(*(elements.map { it.tag }.toTypedArray()))
         }
         return VerticalAnchor.BarrierAnchor(state, tag, barrier)
     }
 
     internal companion object {
-        val verticalAnchorFunctions: Array<Array<ConstraintReference.(Any) -> Unit>> = arrayOf(
+        val verticalAnchorFunctions:
+                Array<Array<ConstraintReference.(Any) -> ConstraintReference>> = arrayOf(
             arrayOf(
-                { other -> startToStart(other) },
-                { other -> startToEnd(other) }
+                { other -> leftToLeft(other) },
+                { other -> leftToRight(other) }
             ),
             arrayOf(
-                { other -> endToStart(other) },
-                { other -> endToEnd(other) }
+                { other -> rightToLeft(other) },
+                { other -> rightToRight(other) }
             )
         )
-        val horizontalAnchorFunctions: Array<Array<ConstraintReference.(Any) -> Unit>> = arrayOf(
+
+        /**
+         * Converts the index (-2 -> start, -1 -> end, 0 -> left, 1 -> right) to an index in
+         * the arrays above (0 -> left, 1 -> right).
+         */
+        // TODO(popam, b/157886946): this is temporary until we can use CL's own RTL handling
+        fun verticalAnchorIndexToFunctionIndex(index: Int, layoutDirection: LayoutDirection) =
+            when {
+                index >= 0 -> index // already left or right
+                layoutDirection == LayoutDirection.Ltr -> 2 + index // start -> left, end -> right
+                else -> -index - 1 // start -> right, end -> left
+            }
+
+        val horizontalAnchorFunctions:
+                Array<Array<ConstraintReference.(Any) -> ConstraintReference>> = arrayOf(
             arrayOf(
                 { other -> topToTop(other) },
                 { other -> topToBottom(other) }
@@ -720,27 +1706,40 @@
                 { other -> bottomToBottom(other) }
             )
         )
-        val baselineAnchorFunction: ConstraintReference.(Any) -> Unit =
+        val baselineAnchorFunction: ConstraintReference.(Any) -> ConstraintReference =
             { other -> baselineToBaseline(other) }
     }
 }
 
+/**
+ * The state of the [ConstraintLayout] solver.
+ */
+class State(val density: Density) : SolverState() {
+    lateinit var rootIncomingConstraints: Constraints
+    lateinit var layoutDirection: LayoutDirection
+
+    override fun convertDimension(value: Any?): Int {
+        return if (value is Dp) {
+            with(density) { value.toIntPx().value }
+        } else {
+            super.convertDimension(value)
+        }
+    }
+
+    override fun reset() {
+        // TODO(b/158197001): this should likely be done by the solver
+        mReferences.clear()
+        mReferences[PARENT] = mParent
+        super.reset()
+    }
+}
+
 private class Measurer internal constructor() : BasicMeasure.Measurer {
     private val root = ConstraintWidgetContainer(0, 0).also { it.measurer = this }
     private val placeables = mutableMapOf<Measurable, Placeable>()
     private lateinit var density: Density
     private lateinit var measureScope: MeasureScope
-    private val state = object : State() {
-        lateinit var rootIncomingConstraints: Constraints
-
-        override fun convertDimension(value: Any?): Int {
-            return if (value is Dp) {
-                with(density) { value.toIntPx().value }
-            } else {
-                super.convertDimension(value)
-            }
-        }
-    }
+    private val state by lazy(LazyThreadSafetyMode.NONE) { State(density) }
 
     val widthConstraintsHolder = IntArray(2)
     val heightConstraintsHolder = IntArray(2)
@@ -750,8 +1749,10 @@
         if (measurable !is Measurable) return
 
         if (DEBUG) {
-            Log.d("CCL", "Measuring ${measurable.tag} with: " +
-                    constraintWidget.toDebugString() + "\n" + measure.toDebugString())
+            Log.d(
+                "CCL", "Measuring ${measurable.tag} with: " +
+                        constraintWidget.toDebugString() + "\n" + measure.toDebugString()
+            )
         }
 
         val initialPlaceable = placeables[measurable]
@@ -787,9 +1788,10 @@
         }
 
         if (constraintWidget.horizontalDimensionBehaviour != MATCH_CONSTRAINT ||
-                constraintWidget.mMatchConstraintDefaultWidth != MATCH_CONSTRAINT_SPREAD ||
-                constraintWidget.verticalDimensionBehaviour != MATCH_CONSTRAINT ||
-                constraintWidget.mMatchConstraintDefaultHeight != MATCH_CONSTRAINT_SPREAD) {
+            constraintWidget.mMatchConstraintDefaultWidth != MATCH_CONSTRAINT_SPREAD ||
+            constraintWidget.verticalDimensionBehaviour != MATCH_CONSTRAINT ||
+            constraintWidget.mMatchConstraintDefaultHeight != MATCH_CONSTRAINT_SPREAD
+        ) {
             if (DEBUG) {
                 Log.d("CCL", "Measuring ${measurable.tag} with $constraints")
             }
@@ -878,6 +1880,7 @@
 
     fun performMeasure(
         constraints: Constraints,
+        layoutDirection: LayoutDirection,
         constraintSet: ConstraintSet,
         measurables: List<Measurable>,
         measureScope: MeasureScope
@@ -885,27 +1888,28 @@
         this.density = measureScope
         this.measureScope = measureScope
         state.reset()
-        // Add tags.
-        measurables.forEach { measurable ->
-            state.map(measurable.tag ?: object : Any() {}, measurable)
-        }
         // Define the size of the ConstraintLayout.
-        state.width(if (constraints.hasFixedWidth) {
-            SolverDimension.Fixed(constraints.maxWidth.value)
-        } else {
-            SolverDimension.Wrap().min(constraints.minWidth.value)
-        })
-        state.height(if (constraints.hasFixedHeight) {
-            SolverDimension.Fixed(constraints.maxHeight.value)
-        } else {
-            SolverDimension.Wrap().min(constraints.minHeight.value)
-        })
+        state.width(
+            if (constraints.hasFixedWidth) {
+                SolverDimension.Fixed(constraints.maxWidth.value)
+            } else {
+                SolverDimension.Wrap().min(constraints.minWidth.value)
+            }
+        )
+        state.height(
+            if (constraints.hasFixedHeight) {
+                SolverDimension.Fixed(constraints.maxHeight.value)
+            } else {
+                SolverDimension.Wrap().min(constraints.minHeight.value)
+            }
+        )
         // Build constraint set and apply it to the state.
-        constraintSet.description(ConstraintSetBuilderScope(state))
+        state.rootIncomingConstraints = constraints
+        state.layoutDirection = layoutDirection
+        constraintSet.applyTo(state, measurables)
         state.apply(root)
         root.width = constraints.maxWidth.value
         root.height = constraints.maxHeight.value
-        state.rootIncomingConstraints = constraints
         root.updateHierarchy()
 
         if (DEBUG) {
@@ -955,8 +1959,8 @@
         for (child in root.children) {
             val measurable = child.companionWidget
             if (measurable !is Measurable) continue
-            // TODO(popam): check if measurer's rtl support should be used instead
-            placeables[measurable]?.place(child.x.ipx, child.y.ipx)
+            // TODO(popam, b/157886946): check if measurer's rtl support should be used instead
+            placeables[measurable]?.placeAbsolute(child.x.ipx, child.y.ipx)
         }
     }
 
@@ -964,6 +1968,9 @@
 }
 
 private typealias SolverDimension = androidx.constraintlayout.core.state.Dimension
+private typealias SolverState = androidx.constraintlayout.core.state.State
+private typealias SolverDirection = androidx.constraintlayout.core.state.State.Direction
+private typealias SolverChain = androidx.constraintlayout.core.state.State.Chain
 private val DEBUG = true
 private fun ConstraintWidget.toDebugString() =
     "$debugName " +
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/Row.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/Row.kt
index c140688..fa9b7e3 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/Row.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/Row.kt
@@ -69,7 +69,7 @@
         orientation = LayoutOrientation.Horizontal,
         modifier = modifier,
         arrangement = horizontalArrangement,
-        crossAxisAlignment = verticalGravity,
+        crossAxisAlignment = CrossAxisAlignment.vertical(verticalGravity),
         crossAxisSize = SizeMode.Wrap,
         children = { RowScope.children() }
     )
@@ -88,7 +88,7 @@
      * @sample androidx.ui.layout.samples.SimpleGravityInRow
      */
     @Stable
-    fun Modifier.gravity(align: Alignment.Vertical) = this + GravityModifier(align)
+    fun Modifier.gravity(align: Alignment.Vertical) = this + VerticalGravityModifier(align)
 
     /**
      * Position the element vertically such that its [alignmentLine] aligns with sibling elements
diff --git a/ui/ui-layout/src/main/java/androidx/ui/layout/RowColumnImpl.kt b/ui/ui-layout/src/main/java/androidx/ui/layout/RowColumnImpl.kt
index 153fa40..e9d2f21 100644
--- a/ui/ui-layout/src/main/java/androidx/ui/layout/RowColumnImpl.kt
+++ b/ui/ui-layout/src/main/java/androidx/ui/layout/RowColumnImpl.kt
@@ -26,21 +26,17 @@
 import androidx.ui.core.IntrinsicMeasureBlock
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutDirection
-import androidx.ui.core.Measurable
 import androidx.ui.core.Measured
 import androidx.ui.core.Modifier
 import androidx.ui.core.ParentDataModifier
 import androidx.ui.core.Placeable
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.ipx
 import androidx.ui.unit.isFinite
 import androidx.ui.unit.max
-import androidx.ui.unit.px
-import androidx.ui.unit.round
-import androidx.ui.unit.toPx
 import androidx.ui.util.fastForEach
+import kotlin.math.roundToInt
 import kotlin.math.sign
 
 /**
@@ -52,17 +48,13 @@
     modifier: Modifier = Modifier,
     arrangement: Arrangement,
     crossAxisSize: SizeMode,
-    crossAxisAlignment: Any,
+    crossAxisAlignment: CrossAxisAlignment,
     children: @Composable () -> Unit
 ) {
     fun Placeable.mainAxisSize() =
         if (orientation == LayoutOrientation.Horizontal) width else height
     fun Placeable.crossAxisSize() =
         if (orientation == LayoutOrientation.Horizontal) height else width
-    fun Measurable.alignmentLineProvider() =
-        (this.crossAxisAlignment as? CrossAxisAlignment)
-            ?.alignmentLineProvider
-            ?: (crossAxisAlignment as? CrossAxisAlignment)?.alignmentLineProvider
 
     Layout(
         children,
@@ -87,15 +79,17 @@
         var crossAxisSpace = IntPx.Zero
 
         var anyAlignWithSiblings = false
-
         val placeables = arrayOfNulls<Placeable>(measurables.size)
+        val rowColumnParentData = Array(measurables.size) { measurables[it].data }
+
         // First measure children with zero weight.
-        for (i in 0 until measurables.size) {
+        for (i in measurables.indices) {
             val child = measurables[i]
-            val weight = child.weight
+            val parentData = rowColumnParentData[i]
+            val weight = parentData.weight
 
             if (weight > 0f) {
-                totalWeight += child.weight
+                totalWeight += weight
             } else {
                 val placeable = child.measure(
                     // Ask for preferred main axis size.
@@ -107,7 +101,7 @@
                 )
                 fixedSpace += placeable.mainAxisSize()
                 crossAxisSpace = max(crossAxisSpace, placeable.crossAxisSize())
-                anyAlignWithSiblings = anyAlignWithSiblings || child.alignmentLineProvider() != null
+                anyAlignWithSiblings = anyAlignWithSiblings || parentData.isRelative
                 placeables[i] = placeable
             }
         }
@@ -120,30 +114,32 @@
         }
 
         val weightUnitSpace = if (totalWeight > 0) {
-            (targetSpace.toPx() - fixedSpace) / totalWeight
+            (targetSpace.value.toFloat() - fixedSpace.value.toFloat()) / totalWeight
         } else {
-            0.px
+            0f
         }
 
-        var remainder = targetSpace - fixedSpace - measurables.sumBy {
-            (weightUnitSpace * it.weight).round().value
+        var remainder = targetSpace - fixedSpace - rowColumnParentData.sumBy {
+            (weightUnitSpace * it.weight).roundToInt()
         }.ipx
 
         var weightedSpace = IntPx.Zero
 
-        for (i in 0 until measurables.size) {
-            val child = measurables[i]
-            val weight = child.weight
-            if (weight > 0f) {
+        for (i in measurables.indices) {
+            if (placeables[i] == null) {
+                val child = measurables[i]
+                val parentData = rowColumnParentData[i]
+                val weight = parentData.weight
+                check(weight > 0) { "All weights <= 0 should have placeables" }
                 val remainderUnit = remainder.value.sign.ipx
                 remainder -= remainderUnit
                 val childMainAxisSize = max(
                     IntPx.Zero,
-                    (weightUnitSpace * child.weight).round() + remainderUnit
+                    (weightUnitSpace * weight).roundToInt().ipx + remainderUnit
                 )
                 val placeable = child.measure(
                     OrientationIndependentConstraints(
-                        if (child.fill && childMainAxisSize.isFinite()) {
+                        if (parentData.fill && childMainAxisSize.isFinite()) {
                             childMainAxisSize
                         } else {
                             IntPx.Zero
@@ -155,7 +151,7 @@
                 )
                 weightedSpace += placeable.mainAxisSize()
                 crossAxisSpace = max(crossAxisSpace, placeable.crossAxisSize())
-                anyAlignWithSiblings = anyAlignWithSiblings || child.alignmentLineProvider() != null
+                anyAlignWithSiblings = anyAlignWithSiblings || parentData.isRelative
                 placeables[i] = placeable
             }
         }
@@ -163,23 +159,19 @@
         var beforeCrossAxisAlignmentLine = IntPx.Zero
         var afterCrossAxisAlignmentLine = IntPx.Zero
         if (anyAlignWithSiblings) {
-            for (i in 0 until placeables.size) {
+            for (i in placeables.indices) {
                 val placeable = placeables[i]!!
-                val lineProvider = measurables[i].alignmentLineProvider()
-                if (lineProvider != null) {
-                    val alignmentLinePosition = when (lineProvider) {
-                        is AlignmentLineProvider.Block ->
-                            lineProvider.lineProviderBlock(Measured(placeable))
-                        is AlignmentLineProvider.Value -> placeable[lineProvider.line]
-                    }
+                val parentData = rowColumnParentData[i]
+                val alignmentLinePosition = parentData.crossAxisAlignment
+                    ?.calculateAlignmentLinePosition(placeable)
+                if (alignmentLinePosition != null) {
                     beforeCrossAxisAlignmentLine = max(
                         beforeCrossAxisAlignmentLine,
-                        alignmentLinePosition ?: 0.ipx
+                        alignmentLinePosition
                     )
                     afterCrossAxisAlignmentLine = max(
                         afterCrossAxisAlignmentLine,
-                        placeable.crossAxisSize() -
-                                (alignmentLinePosition ?: placeable.crossAxisSize())
+                        placeable.crossAxisSize() - alignmentLinePosition
                     )
                 }
             }
@@ -223,64 +215,19 @@
             )
             placeables.forEachIndexed { index, placeable ->
                 placeable!!
-                val measurable = measurables[index]
-                val childCrossAlignment = measurable.crossAxisAlignment ?: crossAxisAlignment
-                val isRtlColumn = orientation == LayoutOrientation.Vertical &&
-                        layoutDirection == LayoutDirection.Rtl
+                val parentData = rowColumnParentData[index]
+                val childCrossAlignment = parentData.crossAxisAlignment ?: crossAxisAlignment
 
-                val crossAxis = when (childCrossAlignment) {
-                    CrossAxisAlignment.Start -> {
-                        if (isRtlColumn) {
-                            crossAxisLayoutSize - placeable.crossAxisSize()
-                        } else {
-                            IntPx.Zero
-                        }
-                    }
-                    CrossAxisAlignment.End -> {
-                        if (isRtlColumn) {
-                            IntPx.Zero
-                        } else {
-                            crossAxisLayoutSize - placeable.crossAxisSize()
-                        }
-                    }
-                    CrossAxisAlignment.Center -> {
-                        Alignment.Center.align(
-                            IntPxSize(
-                                mainAxisLayoutSize - placeable.mainAxisSize(),
-                                crossAxisLayoutSize - placeable.crossAxisSize()
-                            )
-                        ).y
-                    }
-                    is Alignment.Vertical -> childCrossAlignment.align(
-                        crossAxisLayoutSize - placeable.crossAxisSize()
-                    )
-                    is Alignment.Horizontal -> childCrossAlignment.align(
-                        crossAxisLayoutSize - placeable.crossAxisSize(),
+                val crossAxis = childCrossAlignment.align(
+                    size = crossAxisLayoutSize - placeable.crossAxisSize(),
+                    layoutDirection = if (orientation == LayoutOrientation.Horizontal) {
+                        LayoutDirection.Ltr
+                    } else {
                         layoutDirection
-                    )
-                    is CrossAxisAlignment -> {
-                        val provider = childCrossAlignment.alignmentLineProvider
-                        val alignmentLinePosition = when (provider) {
-                            is AlignmentLineProvider.Block ->
-                                provider.lineProviderBlock(Measured(placeable))
-                            is AlignmentLineProvider.Value -> placeable[provider.line]
-                            else -> null
-                        }
-                        if (alignmentLinePosition != null) {
-                            val line = beforeCrossAxisAlignmentLine - alignmentLinePosition
-                            if (orientation == LayoutOrientation.Vertical &&
-                                layoutDirection == LayoutDirection.Rtl
-                            ) {
-                                layoutWidth - line - placeable.width
-                            } else {
-                                line
-                            }
-                        } else {
-                            IntPx.Zero
-                        }
-                    }
-                    else -> 0.ipx
-                }
+                    },
+                    placeable = placeable,
+                    beforeCrossAxisAlignmentLine = beforeCrossAxisAlignmentLine
+                )
 
                 if (orientation == LayoutOrientation.Horizontal) {
                     placeable.placeAbsolute(mainAxisPositions[index], crossAxis)
@@ -387,10 +334,10 @@
         ): List<IntPx> {
             val consumedSize = size.fold(0.ipx) { a, b -> a + b }
             val positions = mutableListOf<IntPx>()
-            var current = (totalSize - consumedSize).toPx() / 2
+            var current = (totalSize - consumedSize).value.toFloat() / 2
             size.fastForEach {
-                positions.add(current.round())
-                current += it
+                positions.add(current.roundToInt().ipx)
+                current += it.value.toFloat()
             }
             return positions
         }
@@ -407,12 +354,12 @@
             layoutDirection: LayoutDirection
         ): List<IntPx> {
             val consumedSize = size.fold(0.ipx) { a, b -> a + b }
-            val gapSize = (totalSize - consumedSize).toPx() / (size.size + 1)
+            val gapSize = (totalSize - consumedSize).value.toFloat() / (size.size + 1)
             val positions = mutableListOf<IntPx>()
             var current = gapSize
             size.fastForEach {
-                positions.add(current.round())
-                current += it.toPx() + gapSize
+                positions.add(current.roundToInt().ipx)
+                current += it.value.toFloat() + gapSize
             }
             return positions
         }
@@ -430,15 +377,15 @@
         ): List<IntPx> {
             val consumedSize = size.fold(0.ipx) { a, b -> a + b }
             val gapSize = if (size.size > 1) {
-                (totalSize - consumedSize).toPx() / (size.size - 1)
+                (totalSize - consumedSize).value.toFloat() / (size.size - 1)
             } else {
-                0.px
+                0f
             }
             val positions = mutableListOf<IntPx>()
-            var current = 0.px
+            var current = 0f
             size.fastForEach {
-                positions.add(current.round())
-                current += it.toPx() + gapSize
+                positions.add(current.roundToInt().ipx)
+                current += it.value.toFloat() + gapSize
             }
             return positions
         }
@@ -457,15 +404,15 @@
         ): List<IntPx> {
             val consumedSize = size.fold(0.ipx) { a, b -> a + b }
             val gapSize = if (size.isNotEmpty()) {
-                (totalSize - consumedSize).toPx() / size.size
+                (totalSize - consumedSize).value.toFloat() / size.size
             } else {
-                0.px
+                0f
             }
             val positions = mutableListOf<IntPx>()
             var current = gapSize / 2
             size.fastForEach {
-                positions.add(current.round())
-                current += it.toPx() + gapSize
+                positions.add(current.roundToInt().ipx)
+                current += it.value.toFloat() + gapSize
             }
             return positions
         }
@@ -560,38 +507,168 @@
  */
 // TODO(popam): refine this API surface with modifiers - add type safety for alignment orientation.
 @Immutable
-class CrossAxisAlignment private constructor(
-    internal val alignmentLineProvider: AlignmentLineProvider? = null
-) {
+sealed class CrossAxisAlignment {
+    /**
+     * Aligns to [size]. If this is a vertical alignment, [layoutDirection] should be
+     * [LayoutDirection.Ltr].
+     *
+     * @param size The remaining space (total size - content size) in the container.
+     * @param layoutDirection The layout direction of the content if horizontal or
+     * [LayoutDirection.Ltr] if vertical.
+     * @param placeable The item being aligned.
+     * @param beforeCrossAxisAlignmentLine The space before the cross-axis alignment line if
+     * an alignment line is being used or 0.ipx if no alignment line is being used.
+     */
+    internal abstract fun align(
+        size: IntPx,
+        layoutDirection: LayoutDirection,
+        placeable: Placeable,
+        beforeCrossAxisAlignmentLine: IntPx
+    ): IntPx
+
+    /**
+     * Returns `true` if this is [Relative].
+     */
+    internal open val isRelative: Boolean
+        get() = false
+
+    /**
+     * Returns the alignment line position relative to the left/top of the space or `null` if
+     * this alignment doesn't rely on alignment lines.
+     */
+    internal open fun calculateAlignmentLinePosition(placeable: Placeable): IntPx? = null
+
     companion object {
         /**
          * Place children such that their center is in the middle of the cross axis.
          */
         @Stable
-        val Center = CrossAxisAlignment(null)
+        val Center: CrossAxisAlignment = CenterCrossAxisAlignment
         /**
          * Place children such that their start edge is aligned to the start edge of the cross
          * axis. TODO(popam): Consider rtl directionality.
          */
         @Stable
-        val Start = CrossAxisAlignment(null)
+        val Start: CrossAxisAlignment = StartCrossAxisAlignment
         /**
          * Place children such that their end edge is aligned to the end edge of the cross
          * axis. TODO(popam): Consider rtl directionality.
          */
         @Stable
-        val End = CrossAxisAlignment(null)
+        val End: CrossAxisAlignment = EndCrossAxisAlignment
         /**
          * Align children by their baseline.
          */
-        fun AlignmentLine(alignmentLine: AlignmentLine) =
-            CrossAxisAlignment(AlignmentLineProvider.Value(alignmentLine))
+        fun AlignmentLine(alignmentLine: AlignmentLine): CrossAxisAlignment =
+            AlignmentLineCrossAxisAlignment(AlignmentLineProvider.Value(alignmentLine))
         /**
          * Align children relative to their siblings using the alignment line provided as a
          * parameter using [AlignmentLineProvider].
          */
-        internal fun Relative(alignmentLineProvider: AlignmentLineProvider) =
-            CrossAxisAlignment(alignmentLineProvider)
+        internal fun Relative(alignmentLineProvider: AlignmentLineProvider): CrossAxisAlignment =
+            AlignmentLineCrossAxisAlignment(alignmentLineProvider)
+
+        /**
+         * Align children with vertical alignment.
+         */
+        internal fun vertical(vertical: Alignment.Vertical): CrossAxisAlignment =
+            VerticalCrossAxisAlignment(vertical)
+
+        /**
+         * Align children with horizontal alignment.
+         */
+        internal fun horizontal(horizontal: Alignment.Horizontal): CrossAxisAlignment =
+            HorizontalCrossAxisAlignment(horizontal)
+    }
+
+    private object CenterCrossAxisAlignment : CrossAxisAlignment() {
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            return size / 2
+        }
+    }
+
+    private object StartCrossAxisAlignment : CrossAxisAlignment() {
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            return if (layoutDirection == LayoutDirection.Ltr) 0.ipx else size
+        }
+    }
+
+    private object EndCrossAxisAlignment : CrossAxisAlignment() {
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            return if (layoutDirection == LayoutDirection.Ltr) size else 0.ipx
+        }
+    }
+
+    private class AlignmentLineCrossAxisAlignment(
+        val alignmentLineProvider: AlignmentLineProvider
+    ) : CrossAxisAlignment() {
+        override val isRelative: Boolean
+            get() = true
+
+        override fun calculateAlignmentLinePosition(placeable: Placeable): IntPx? {
+            return alignmentLineProvider.calculateAlignmentLinePosition(placeable)
+        }
+
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            val alignmentLinePosition =
+                alignmentLineProvider.calculateAlignmentLinePosition(placeable)
+            return if (alignmentLinePosition != null) {
+                val line = beforeCrossAxisAlignmentLine - alignmentLinePosition
+                if (layoutDirection == LayoutDirection.Rtl) {
+                    size - line
+                } else {
+                    line
+                }
+            } else {
+                IntPx.Zero
+            }
+        }
+    }
+
+    private class VerticalCrossAxisAlignment(
+        val vertical: Alignment.Vertical
+    ) : CrossAxisAlignment() {
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            return vertical.align(size)
+        }
+    }
+
+    private class HorizontalCrossAxisAlignment(
+        val horizontal: Alignment.Horizontal
+    ) : CrossAxisAlignment() {
+        override fun align(
+            size: IntPx,
+            layoutDirection: LayoutDirection,
+            placeable: Placeable,
+            beforeCrossAxisAlignmentLine: IntPx
+        ): IntPx {
+            return horizontal.align(size, layoutDirection)
+        }
     }
 }
 
@@ -644,14 +721,20 @@
         }
 }
 
-private val IntrinsicMeasurable.weight: Float
-    get() = (parentData as? RowColumnParentData)?.weight ?: 0f
+private val IntrinsicMeasurable.data: RowColumnParentData?
+    get() = parentData as? RowColumnParentData
 
-private val IntrinsicMeasurable.fill: Boolean
-    get() = (parentData as? RowColumnParentData)?.fill ?: true
+private val RowColumnParentData?.weight: Float
+    get() = this?.weight ?: 0f
 
-private val IntrinsicMeasurable.crossAxisAlignment: Any?
-    get() = (parentData as? RowColumnParentData)?.crossAxisAlignment
+private val RowColumnParentData?.fill: Boolean
+    get() = this?.fill ?: true
+
+private val RowColumnParentData?.crossAxisAlignment: CrossAxisAlignment?
+    get() = this?.crossAxisAlignment
+
+private val RowColumnParentData?.isRelative: Boolean
+    get() = this.crossAxisAlignment?.isRelative ?: false
 
 private /*inline*/ fun MinIntrinsicWidthMeasureBlock(orientation: LayoutOrientation) =
     if (orientation == LayoutOrientation.Horizontal) {
@@ -786,7 +869,7 @@
     var fixedSpace = 0.ipx
     var totalWeight = 0f
     children.fastForEach { child ->
-        val weight = child.weight
+        val weight = child.data.weight
         val size = child.mainAxisSize(crossAxisAvailable)
         if (weight == 0f) {
             fixedSpace += size
@@ -808,7 +891,7 @@
     var crossAxisMax = 0.ipx
     var totalWeight = 0f
     children.fastForEach { child ->
-        val weight = child.weight
+        val weight = child.data.weight
         if (weight == 0f) {
             val mainAxisSpace = child.mainAxisSize(IntPx.Infinity)
             fixedSpace += mainAxisSpace
@@ -825,8 +908,9 @@
     }
 
     children.fastForEach { child ->
-        if (child.weight > 0f) {
-            crossAxisMax = max(crossAxisMax, child.crossAxisSize(weightUnitSpace * child.weight))
+        val weight = child.data.weight
+        if (weight > 0f) {
+            crossAxisMax = max(crossAxisMax, child.crossAxisSize(weightUnitSpace * weight))
         }
     }
     return crossAxisMax
@@ -864,10 +948,22 @@
     }
 }
 
-internal data class GravityModifier(val alignment: Any) : ParentDataModifier {
+internal data class HorizontalGravityModifier(
+    val horizontal: Alignment.Horizontal
+) : ParentDataModifier {
     override fun Density.modifyParentData(parentData: Any?): RowColumnParentData {
         return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
-            it.crossAxisAlignment = alignment
+            it.crossAxisAlignment = CrossAxisAlignment.horizontal(horizontal)
+        }
+    }
+}
+
+internal data class VerticalGravityModifier(
+    val vertical: Alignment.Vertical
+) : ParentDataModifier {
+    override fun Density.modifyParentData(parentData: Any?): RowColumnParentData {
+        return ((parentData as? RowColumnParentData) ?: RowColumnParentData()).also {
+            it.crossAxisAlignment = CrossAxisAlignment.vertical(vertical)
         }
     }
 }
@@ -878,13 +974,25 @@
 internal data class RowColumnParentData(
     var weight: Float = 0f,
     var fill: Boolean = true,
-    var crossAxisAlignment: Any? = null
+    var crossAxisAlignment: CrossAxisAlignment? = null
 )
 
 /**
  * Provides the alignment line.
  */
 internal sealed class AlignmentLineProvider {
-    data class Block(val lineProviderBlock: (Measured) -> IntPx) : AlignmentLineProvider()
-    data class Value(val line: AlignmentLine) : AlignmentLineProvider()
-}
\ No newline at end of file
+    abstract fun calculateAlignmentLinePosition(placeable: Placeable): IntPx?
+    data class Block(val lineProviderBlock: (Measured) -> IntPx) : AlignmentLineProvider() {
+        override fun calculateAlignmentLinePosition(
+            placeable: Placeable
+        ): IntPx? {
+            return lineProviderBlock(Measured(placeable))
+        }
+    }
+
+    data class Value(val line: AlignmentLine) : AlignmentLineProvider() {
+        override fun calculateAlignmentLinePosition(placeable: Placeable): IntPx? {
+            return placeable[line]
+        }
+    }
+}
diff --git a/ui/ui-material/api/0.1.0-dev14.txt b/ui/ui-material/api/0.1.0-dev14.txt
index 1c47c92..a6e6764 100644
--- a/ui/ui-material/api/0.1.0-dev14.txt
+++ b/ui/ui-material/api/0.1.0-dev14.txt
@@ -324,25 +324,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -351,18 +336,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/api/current.txt b/ui/ui-material/api/current.txt
index 1c47c92..a6e6764 100644
--- a/ui/ui-material/api/current.txt
+++ b/ui/ui-material/api/current.txt
@@ -324,25 +324,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -351,18 +336,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-material/api/public_plus_experimental_0.1.0-dev14.txt
index 1c47c92..a6e6764 100644
--- a/ui/ui-material/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-material/api/public_plus_experimental_0.1.0-dev14.txt
@@ -324,25 +324,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -351,18 +336,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/api/public_plus_experimental_current.txt b/ui/ui-material/api/public_plus_experimental_current.txt
index 1c47c92..a6e6764 100644
--- a/ui/ui-material/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/api/public_plus_experimental_current.txt
@@ -324,25 +324,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -351,18 +336,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/api/restricted_0.1.0-dev14.txt b/ui/ui-material/api/restricted_0.1.0-dev14.txt
index 863b170..1cf43fc 100644
--- a/ui/ui-material/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-material/api/restricted_0.1.0-dev14.txt
@@ -325,25 +325,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -352,18 +337,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/api/restricted_current.txt b/ui/ui-material/api/restricted_current.txt
index 863b170..1cf43fc 100644
--- a/ui/ui-material/api/restricted_current.txt
+++ b/ui/ui-material/api/restricted_current.txt
@@ -325,25 +325,10 @@
 
 package androidx.ui.material.ripple {
 
-  public final class DefaultRippleEffectFactory implements androidx.ui.material.ripple.RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-    field public static final androidx.ui.material.ripple.DefaultRippleEffectFactory! INSTANCE;
+  public final class RippleAnimationKt {
   }
 
-  public final class DefaultRippleEffectKt {
-  }
-
-  public interface RippleEffect {
-    method public default void dispose();
-    method public void draw-z8Px3OI(androidx.ui.graphics.drawscope.DrawScope, long color);
-    method public void finish(boolean canceled);
-  }
-
-  public interface RippleEffectFactory {
-    method public androidx.ui.material.ripple.RippleEffect create-muzrHoo(androidx.ui.unit.PxSize size, androidx.ui.unit.PxPosition startPosition, androidx.ui.unit.Density density, androidx.ui.unit.Dp? radius, boolean clipped, androidx.animation.AnimationClockObservable clock, kotlin.jvm.functions.Function1<? super androidx.ui.material.ripple.RippleEffect,kotlin.Unit> onAnimationFinished);
-  }
-
-  public final class RippleIndication implements androidx.ui.foundation.Indication {
+  @androidx.compose.Stable public final class RippleIndication implements androidx.ui.foundation.Indication {
     method public androidx.ui.foundation.IndicationInstance createInstance();
   }
 
@@ -352,18 +337,16 @@
   }
 
   public final class RippleKt {
-    method public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
+    method @Deprecated public static androidx.ui.core.Modifier ripple-Eb40wiw(androidx.ui.core.Modifier, boolean bounded = true, androidx.ui.unit.Dp? radius = null, long color = Color.Unset, boolean enabled = true, androidx.animation.AnimationClockObservable? clock = null);
   }
 
-  public final class RippleTheme {
-    ctor public RippleTheme(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public androidx.ui.material.ripple.RippleEffectFactory component1();
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> component2();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> component3();
-    method public androidx.ui.material.ripple.RippleTheme copy(androidx.ui.material.ripple.RippleEffectFactory factory, kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> defaultColor, kotlin.jvm.functions.Function0<java.lang.Float> opacity);
-    method public kotlin.jvm.functions.Function0<androidx.ui.graphics.Color> getDefaultColor();
-    method public androidx.ui.material.ripple.RippleEffectFactory getFactory();
-    method public kotlin.jvm.functions.Function0<java.lang.Float> getOpacity();
+  public interface RippleOpacity {
+    method public float opacityForInteraction(androidx.ui.foundation.Interaction interaction);
+  }
+
+  public interface RippleTheme {
+    method @androidx.compose.Composable public long defaultColor();
+    method @androidx.compose.Composable public androidx.ui.material.ripple.RippleOpacity rippleOpacity();
   }
 
   public final class RippleThemeKt {
diff --git a/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt b/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt
index 0eb2204..797bbef 100644
--- a/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt
+++ b/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt
@@ -16,8 +16,13 @@
 
 package androidx.ui.material.icons.test
 
+import android.app.Activity
 import android.graphics.Bitmap
 import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.view.PixelCopy
+import android.view.ViewTreeObserver
 import androidx.activity.ComponentActivity
 import androidx.compose.Composable
 import androidx.compose.Composition
@@ -39,17 +44,21 @@
 import androidx.ui.layout.Stack
 import androidx.ui.layout.preferredSize
 import androidx.ui.res.vectorResource
+import androidx.ui.test.SemanticsNodeInteraction
 import androidx.ui.test.android.AndroidComposeTestRule
-import androidx.ui.test.captureToBitmap
 import androidx.ui.test.findByTag
 import androidx.ui.test.runOnUiThread
 import androidx.ui.test.waitForIdle
 import androidx.ui.unit.ipx
+import androidx.ui.unit.toRect
 import com.google.common.truth.Truth
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
 import kotlin.reflect.KProperty0
 import kotlin.reflect.jvm.javaGetter
 
@@ -114,9 +123,11 @@
 
             assertVectorAssetsAreEqual(xmlVector!!, programmaticVector, iconName)
 
+            val activity = composeTestRule.activityTestRule.activity
+
             assertBitmapsAreEqual(
-                findByTag(XmlTestTag).captureToBitmap(),
-                findByTag(ProgrammaticTestTag).captureToBitmap(),
+                findByTag(XmlTestTag).fastCaptureToBitmap(activity),
+                findByTag(ProgrammaticTestTag).fastCaptureToBitmap(activity),
                 iconName
             )
 
@@ -212,3 +223,75 @@
         }
     }
 }
+
+/**
+ * Taken from before http://aosp/1318899
+ *
+ * The current SemanticsNodeInteraction.captureToBitmap is unfortunately 3x~ slower, so
+ * although this approach doesn't handle cutouts / action bars, in this specific test it is ok to
+ * use it to speed up the test run for this large test.
+ */
+private fun SemanticsNodeInteraction.fastCaptureToBitmap(activity: Activity): Bitmap {
+    // First we wait for the drawing to happen
+    val drawLatch = CountDownLatch(1)
+    val decorView = activity.window.decorView
+    val handler = Handler(Looper.getMainLooper())
+    handler.post {
+        if (Build.VERSION.SDK_INT >= 29) {
+            decorView.viewTreeObserver.registerFrameCommitCallback {
+                drawLatch.countDown()
+            }
+        } else {
+            decorView.viewTreeObserver.addOnDrawListener(object : ViewTreeObserver.OnDrawListener {
+                var handled = false
+                override fun onDraw() {
+                    if (!handled) {
+                        handled = true
+                        handler.post {
+                            drawLatch.countDown()
+                            decorView.viewTreeObserver.removeOnDrawListener(this)
+                        }
+                    }
+                }
+            })
+        }
+        decorView.invalidate()
+    }
+    if (!drawLatch.await(1, TimeUnit.SECONDS)) {
+        throw AssertionError("Failed waiting for DecorView redraw!")
+    }
+
+    val node = fetchSemanticsNode("Failed to capture a node to bitmap.")
+    val captureRect = node.globalBounds.toRect()
+
+    // and then request the pixel copy of the drawn buffer
+    val destBitmap = Bitmap.createBitmap(
+        captureRect.width.roundToInt(),
+        captureRect.height.roundToInt(),
+        Bitmap.Config.ARGB_8888
+    )
+
+    val srcRect = android.graphics.Rect(
+        captureRect.left.roundToInt(),
+        captureRect.top.roundToInt(),
+        captureRect.right.roundToInt(),
+        captureRect.bottom.roundToInt()
+    )
+
+    val latch = CountDownLatch(1)
+    var copyResult = 0
+    val onCopyFinished = PixelCopy.OnPixelCopyFinishedListener { result ->
+        copyResult = result
+        latch.countDown()
+    }
+
+    PixelCopy.request(activity.window, srcRect, destBitmap, onCopyFinished, handler)
+
+    if (!latch.await(1, TimeUnit.SECONDS)) {
+        throw AssertionError("Failed waiting for PixelCopy!")
+    }
+    if (copyResult != PixelCopy.SUCCESS) {
+        throw AssertionError("PixelCopy failed!")
+    }
+    return destBitmap
+}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ColorPickerDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ColorPickerDemo.kt
index 23d1bfd..9ca4548 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ColorPickerDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ColorPickerDemo.kt
@@ -69,7 +69,6 @@
 import androidx.ui.material.TopAppBar
 import androidx.ui.text.style.TextAlign
 import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.dp
 import java.util.Locale
 
@@ -97,7 +96,7 @@
             .aspectRatio(1f)
     ) {
         val diameter = constraints.maxWidth.value
-        var position by state { PxPosition.Origin }
+        var position by state { Offset.Zero }
         val colorWheel = remember(diameter) { ColorWheel(diameter) }
 
         var isDragging by state { false }
@@ -136,17 +135,17 @@
  */
 @Composable
 private fun SimplePointerInput(
-    position: PxPosition,
-    onPositionChange: (PxPosition) -> Unit,
+    position: Offset,
+    onPositionChange: (Offset) -> Unit,
     onDragStateChange: (Boolean) -> Unit
 ): Modifier {
     val observer = object : DragObserver {
-        override fun onStart(downPosition: PxPosition) {
+        override fun onStart(downPosition: Offset) {
             onDragStateChange(true)
             onPositionChange(downPosition)
         }
 
-        override fun onDrag(dragDistance: PxPosition): PxPosition {
+        override fun onDrag(dragDistance: Offset): Offset {
             onPositionChange(position + dragDistance)
             return dragDistance
         }
@@ -155,7 +154,7 @@
             onDragStateChange(false)
         }
 
-        override fun onStop(velocity: PxPosition) {
+        override fun onStop(velocity: Offset) {
             onDragStateChange(false)
         }
     }
@@ -167,7 +166,7 @@
  * Magnifier displayed on top of [position] with the currently selected [color].
  */
 @Composable
-private fun Magnifier(visible: Boolean, position: PxPosition, color: Color) {
+private fun Magnifier(visible: Boolean, position: Offset, color: Color) {
     val offset = with(DensityAmbient.current) {
         Modifier.offset(
             position.x.toDp() - MagnifierWidth / 2,
@@ -340,7 +339,7 @@
  * @return the matching color for [position] inside [ColorWheel], or `null` if there is no color
  * or the color is partially transparent.
  */
-private fun ColorWheel.colorForPosition(position: PxPosition): Color {
+private fun ColorWheel.colorForPosition(position: Offset): Color {
     val x = position.x.toInt().coerceAtLeast(0)
     val y = position.y.toInt().coerceAtLeast(0)
     with(image.toPixelMap()) {
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/TabSamples.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/TabSamples.kt
index 209d646..b2c6788 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/TabSamples.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/TabSamples.kt
@@ -55,7 +55,6 @@
 import androidx.ui.material.icons.Icons
 import androidx.ui.material.icons.filled.Favorite
 import androidx.ui.unit.dp
-import androidx.ui.unit.toPx
 
 @Sampled
 @Composable
@@ -298,8 +297,8 @@
             transitionDefinition {
                 tabPositions.forEachIndexed { index, position ->
                     state(index) {
-                        this[indicatorStart] = position.left.toPx().value
-                        this[indicatorEnd] = position.right.toPx().value
+                        this[indicatorStart] = position.left.value.toFloat()
+                        this[indicatorEnd] = position.right.value.toFloat()
                         this[indicatorColor] = colors[index % colors.size]
                     }
                 }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
index 307f43c..ff9e9cb 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
@@ -37,9 +37,7 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
 import androidx.ui.unit.sp
-import androidx.ui.unit.toPx
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -94,7 +92,7 @@
                         Text("title", Modifier.onPositioned { coords: LayoutCoordinates ->
                             titleCoords = coords
                             titleLastBaselineRelativePosition =
-                                coords[LastBaseline]!!.toPx().value
+                                coords[LastBaseline]!!.value.toFloat()
                         })
                     },
                     actions = {
@@ -110,7 +108,7 @@
 
             // Navigation icon should be 4.dp from the start
             val navigationIconPositionX = navigationIconCoords!!.globalPosition.x
-            val navigationIconExpectedPositionX = AppBarStartAndEndPadding.toIntPx().toPx().value
+            val navigationIconExpectedPositionX = AppBarStartAndEndPadding.toIntPx().value.toFloat()
             assertThat(navigationIconPositionX).isEqualTo(navigationIconExpectedPositionX)
 
             // Navigation icon should be 4.dp from the bottom
@@ -130,14 +128,14 @@
             val titleLastBaselinePositionY = titleLastBaselineRelativePosition!! +
                     titleCoords!!.globalPosition.y
             // Baseline should be 20.sp from the bottom of the app bar
-            val titleExpectedLastBaselinePositionY = (appBarBottomEdgeY.px - 20.sp.toIntPx()
-                .toPx()).value
+            val titleExpectedLastBaselinePositionY =
+                (appBarBottomEdgeY - 20.sp.toIntPx().value.toFloat())
             assertThat(titleLastBaselinePositionY).isEqualTo(titleExpectedLastBaselinePositionY)
 
             // Action should be placed at the end
             val actionPositionX = actionCoords!!.globalPosition.x
             val actionExpectedPositionX =
-                expectedActionPosition(appBarCoords!!.size.width.toPx().value)
+                expectedActionPosition(appBarCoords!!.size.width.value.toFloat())
             assertThat(actionPositionX).isEqualTo(actionExpectedPositionX)
 
             // Action should be 4.dp from the bottom
@@ -172,13 +170,13 @@
             // Title should now be placed 16.dp from the start, as there is no navigation icon
             val titlePositionX = titleCoords!!.globalPosition.x
             // 4.dp padding for the whole app bar + 12.dp inset
-            val titleExpectedPositionX = (4.dp.toIntPx() + 12.dp.toIntPx()).toPx().value
+            val titleExpectedPositionX = (4.dp.toIntPx() + 12.dp.toIntPx()).value.toFloat()
             assertThat(titlePositionX).isEqualTo(titleExpectedPositionX)
 
             // Action should still be placed at the end
             val actionPositionX = actionCoords!!.globalPosition.x
             val actionExpectedPositionX =
-                expectedActionPosition(appBarCoords!!.size.width.toPx().value)
+                expectedActionPosition(appBarCoords!!.size.width.value.toFloat())
             assertThat(actionPositionX).isEqualTo(actionExpectedPositionX)
         }
     }
@@ -228,7 +226,7 @@
         composeTestRule.runOnIdleComposeWithDensity {
             // Child icon should be 4.dp from the start
             val childIconPositionX = childCoords!!.globalPosition.x
-            val childIconExpectedPositionX = AppBarStartAndEndPadding.toIntPx().toPx().value
+            val childIconExpectedPositionX = AppBarStartAndEndPadding.toIntPx().value.toFloat()
             assertThat(childIconPositionX).isEqualTo(childIconExpectedPositionX)
 
             val appBarBottomEdgeY = appBarCoords!!.globalPosition.y +
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 30f953e..320ba93 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
@@ -38,7 +38,6 @@
 import androidx.ui.test.findByText
 import androidx.ui.test.isInMutuallyExclusiveGroup
 import androidx.ui.unit.dp
-import androidx.ui.unit.toPx
 import com.google.common.truth.Truth
 import org.junit.Rule
 import org.junit.Test
@@ -145,22 +144,23 @@
             val textBaseline = 12.dp.toIntPx().value.toFloat()
 
             // Relative position of the baseline to the top of text
-            val relativeTextBaseline = textCoords[LastBaseline]!!.toPx().value
+            val relativeTextBaseline = textCoords[LastBaseline]!!.value.toFloat()
             // Absolute y position of the text baseline
             val absoluteTextBaseline = textCoords.globalPosition.y + relativeTextBaseline
 
-            val itemBottom = itemCoords.size.height.toPx().value + itemCoords.globalPosition.y
+            val itemBottom = itemCoords.size.height.value.toFloat() + itemCoords.globalPosition.y
             // Text baseline should be 12.dp from the bottom of the item
             Truth.assertThat(absoluteTextBaseline).isEqualTo(itemBottom - textBaseline)
 
             // The icon should be centered in the item
-            val iconExpectedX = (itemCoords.size.width.toPx() - iconCoords.size.width.toPx()) / 2
+            val iconExpectedX = (itemCoords.size.width.value.toFloat() - iconCoords.size.width
+                .value.toFloat()) / 2
             // The bottom of the icon is 12.dp above the text baseline
             val iconExpectedY =
                 absoluteTextBaseline - 12.dp.toIntPx().value.toFloat() -
                         iconCoords.size.height.value
 
-            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(iconExpectedX.value)
+            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(iconExpectedX)
             Truth.assertThat(iconCoords.globalPosition.y).isEqualTo(iconExpectedY)
         }
     }
@@ -204,11 +204,13 @@
 
         composeTestRule.runOnIdleComposeWithDensity {
             // The icon should be centered in the item
-            val iconExpectedX = (itemCoords.size.width.toPx() - iconCoords.size.width.toPx()) / 2
-            val iconExpectedY = (itemCoords.size.height - iconCoords.size.height) / 2
+            val iconExpectedX = (itemCoords.size.width.value.toFloat() -
+                    iconCoords.size.width.value.toFloat()) / 2
+            val iconExpectedY = ((itemCoords.size.height - iconCoords.size.height) / 2)
+                .value.toFloat()
 
-            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(iconExpectedX.value)
-            Truth.assertThat(iconCoords.globalPosition.y).isEqualTo(iconExpectedY.toPx().value)
+            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(iconExpectedX)
+            Truth.assertThat(iconCoords.globalPosition.y).isEqualTo(iconExpectedY)
         }
     }
 
@@ -238,11 +240,12 @@
 
         composeTestRule.runOnIdleComposeWithDensity {
             // The icon should be centered in the item, as there is no text placeable provided
-            val iconExpectedX = (itemCoords.size.width.toPx() - iconCoords.size.width.toPx()) / 2
-            val iconExpectedY = (itemCoords.size.height.toPx() - iconCoords.size.height.toPx()) / 2
+            val iconExpectedX = (itemCoords.size.width - iconCoords.size.width) / 2
+            val iconExpectedY = (itemCoords.size.height - iconCoords.size.height) / 2
 
-            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(iconExpectedX.value)
-            Truth.assertThat(iconCoords.globalPosition.y).isEqualTo(iconExpectedY.value)
+            Truth.assertThat(iconCoords.globalPosition.x).isWithin(1f).of(
+                iconExpectedX.value.toFloat())
+            Truth.assertThat(iconCoords.globalPosition.y).isEqualTo(iconExpectedY.value.toFloat())
         }
     }
 
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 15c907b..e8c9f31 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
@@ -56,13 +56,12 @@
 import androidx.ui.test.findByText
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.center
 import androidx.ui.unit.dp
 import androidx.ui.unit.height
 import androidx.ui.unit.sp
-import androidx.ui.unit.toPx
 import androidx.ui.unit.width
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -550,8 +549,8 @@
         }
 
         runOnIdleCompose {
-            val topLeft = childCoordinates!!.localToGlobal(PxPosition.Origin).x -
-                    parentCoordinates!!.localToGlobal(PxPosition.Origin).x
+            val topLeft = childCoordinates!!.localToGlobal(Offset.Zero).x -
+                    parentCoordinates!!.localToGlobal(Offset.Zero).x
             val currentPadding = with(composeTestRule.density) {
                 padding.toIntPx().value.toFloat()
             }
@@ -560,7 +559,7 @@
     }
 }
 
-fun assertWithinOnePixel(expected: PxPosition, actual: PxPosition) {
+fun assertWithinOnePixel(expected: Offset, actual: Offset) {
     assertWithinOnePixel(expected.x, actual.x)
     assertWithinOnePixel(expected.y, actual.y)
 }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
index c2310b0..ffd799b 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
@@ -21,7 +21,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.screenshot.AndroidXScreenshotTestRule
 import androidx.test.screenshot.assertAgainstGolden
-import androidx.test.screenshot.matchers.MSSIMMatcher
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
 import androidx.ui.layout.wrapContentSize
@@ -49,8 +48,6 @@
 
     val wrap = Modifier.wrapContentSize(Alignment.TopStart)
 
-    val matcher = MSSIMMatcher(threshold = 0.96)
-
     @Test
     fun checkBoxTest_checked() {
         composeTestRule.setMaterialContent {
@@ -58,7 +55,7 @@
         }
         find(isToggleable())
             .captureToBitmap()
-            .assertAgainstGolden(screenshotRule, "checkbox_checked", matcher)
+            .assertAgainstGolden(screenshotRule, "checkbox_checked")
     }
 
     @Test
@@ -68,7 +65,7 @@
         }
         find(isToggleable())
             .captureToBitmap()
-            .assertAgainstGolden(screenshotRule, "checkbox_unchecked", matcher)
+            .assertAgainstGolden(screenshotRule, "checkbox_unchecked")
     }
 
     @Test
@@ -90,7 +87,7 @@
 
         find(isToggleable())
             .captureToBitmap()
-            .assertAgainstGolden(screenshotRule, "checkbox_animateToChecked", matcher)
+            .assertAgainstGolden(screenshotRule, "checkbox_animateToChecked")
     }
 
     @Test
@@ -112,6 +109,6 @@
 
         find(isToggleable())
             .captureToBitmap()
-            .assertAgainstGolden(screenshotRule, "checkbox_animateToUnchecked", matcher)
+            .assertAgainstGolden(screenshotRule, "checkbox_animateToUnchecked")
     }
 }
\ No newline at end of file
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 1020729..55bd392 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
@@ -36,11 +36,9 @@
 import androidx.ui.test.sendClick
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.height
-import androidx.ui.unit.px
-import androidx.ui.unit.round
 import androidx.ui.unit.width
 import com.google.common.truth.Truth.assertThat
 import org.junit.Ignore
@@ -61,11 +59,11 @@
 
     @Test
     fun modalDrawer_testOffset_whenOpened() {
-        var position: PxPosition? = null
+        var position: Offset? = null
         composeTestRule.setMaterialContent {
             ModalDrawerLayout(DrawerState.Opened, {}, drawerContent = {
                 Box(Modifier.fillMaxSize().onPositioned { coords: LayoutCoordinates ->
-                    position = coords.localToGlobal(PxPosition.Origin)
+                    position = coords.localToGlobal(Offset.Zero)
                 })
             }, bodyContent = emptyContent())
         }
@@ -76,17 +74,17 @@
 
     @Test
     fun modalDrawer_testOffset_whenClosed() {
-        var position: PxPosition? = null
+        var position: Offset? = null
         composeTestRule.setMaterialContent {
             ModalDrawerLayout(DrawerState.Closed, {}, drawerContent = {
                 Box(Modifier.fillMaxSize().onPositioned { coords: LayoutCoordinates ->
-                    position = coords.localToGlobal(PxPosition.Origin)
+                    position = coords.localToGlobal(Offset.Zero)
                 })
             }, bodyContent = emptyContent())
         }
         val width = composeTestRule.displayMetrics.widthPixels
         runOnIdleCompose {
-            assertThat(position!!.x.px.round().value).isEqualTo(-width)
+            assertThat(position!!.x.roundToInt()).isEqualTo(-width)
         }
     }
 
@@ -110,11 +108,11 @@
 
     @Test
     fun bottomDrawer_testOffset_whenOpened() {
-        var position: PxPosition? = null
+        var position: Offset? = null
         composeTestRule.setMaterialContent {
             BottomDrawerLayout(DrawerState.Opened, {}, drawerContent = {
                 Box(Modifier.fillMaxSize().onPositioned { coords: LayoutCoordinates ->
-                    position = coords.localToGlobal(PxPosition.Origin)
+                    position = coords.localToGlobal(Offset.Zero)
                 })
             }, bodyContent = emptyContent())
         }
@@ -124,23 +122,23 @@
         // temporary calculation of landscape screen
         val expectedHeight = if (width > height) 0 else (height / 2f).roundToInt()
         runOnIdleCompose {
-            assertThat(position!!.y.px.round().value).isEqualTo(expectedHeight)
+            assertThat(position!!.y.roundToInt()).isEqualTo(expectedHeight)
         }
     }
 
     @Test
     fun bottomDrawer_testOffset_whenClosed() {
-        var position: PxPosition? = null
+        var position: Offset? = null
         composeTestRule.setMaterialContent {
             BottomDrawerLayout(DrawerState.Closed, {}, drawerContent = {
                 Box(Modifier.fillMaxSize().onPositioned { coords: LayoutCoordinates ->
-                    position = coords.localToGlobal(PxPosition.Origin)
+                    position = coords.localToGlobal(Offset.Zero)
                 })
             }, bodyContent = emptyContent())
         }
         val height = composeTestRule.displayMetrics.heightPixels
         runOnIdleCompose {
-            assertThat(position!!.y.px.round().value).isEqualTo(height)
+            assertThat(position!!.y.roundToInt()).isEqualTo(height)
         }
     }
 
@@ -156,11 +154,11 @@
                 drawerContent = {
                     Box(
                         Modifier.fillMaxSize().onPositioned { info: LayoutCoordinates ->
-                            val pos = info.localToGlobal(PxPosition.Origin)
+                            val pos = info.localToGlobal(Offset.Zero)
                             if (pos.x == 0.0f) {
                                 // If fully opened, mark the openedLatch if present
                                 openedLatch?.countDown()
-                            } else if (-pos.x.px.round() == contentWidth) {
+                            } else if (-pos.x.roundToInt() == contentWidth?.value) {
                                 // If fully closed, mark the closedLatch if present
                                 closedLatch?.countDown()
                             }
@@ -229,7 +227,7 @@
         findByTag("Drawer").doGesture {
             val left = 1.0f
             val centerY = (globalBounds.height / 2)
-            sendClick(PxPosition(left, centerY))
+            sendClick(Offset(left, centerY))
         }
 
         runOnIdleCompose {
@@ -250,11 +248,11 @@
             BottomDrawerLayout(drawerState.value, { drawerState.value = it },
                 drawerContent = {
                     Box(Modifier.fillMaxSize().onPositioned { info: LayoutCoordinates ->
-                        val pos = info.localToGlobal(PxPosition.Origin)
-                        if (pos.y.px.round() == openedHeight) {
+                        val pos = info.localToGlobal(Offset.Zero)
+                        if (pos.y.roundToInt() == openedHeight?.value) {
                             // If fully opened, mark the openedLatch if present
                             openedLatch?.countDown()
-                        } else if (pos.y.px.round() == contentHeight) {
+                        } else if (pos.y.roundToInt() == contentHeight?.value) {
                             // If fully closed, mark the closedLatch if present
                             closedLatch?.countDown()
                         }
@@ -328,7 +326,7 @@
             val bounds = globalBounds
             val centerX = bounds.width / 2
             val bottom = bounds.height - 1.0f
-            sendClick(PxPosition(centerX, bottom))
+            sendClick(Offset(centerX, bottom))
         }
 
         assertThat(drawerClicks).isEqualTo(1)
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/FilledTextFieldTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/FilledTextFieldTest.kt
index 3e77456..2f4cd3e 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/FilledTextFieldTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/FilledTextFieldTest.kt
@@ -18,6 +18,7 @@
 
 import android.os.Build
 import androidx.compose.Providers
+import androidx.compose.remember
 import androidx.compose.state
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
@@ -29,6 +30,7 @@
 import androidx.ui.core.testTag
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.Text
+import androidx.ui.foundation.TextField
 import androidx.ui.foundation.TextFieldValue
 import androidx.ui.foundation.contentColor
 import androidx.ui.foundation.currentTextStyle
@@ -42,8 +44,10 @@
 import androidx.ui.input.TextInputService
 import androidx.ui.layout.Column
 import androidx.ui.layout.Stack
+import androidx.ui.layout.fillMaxWidth
 import androidx.ui.layout.preferredHeight
 import androidx.ui.layout.preferredSize
+import androidx.ui.test.assertPixels
 import androidx.ui.test.assertShape
 import androidx.ui.test.captureToBitmap
 import androidx.ui.test.createComposeRule
@@ -53,14 +57,15 @@
 import androidx.ui.test.findByTag
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.sendClick
+import androidx.ui.test.sendSwipeDown
+import androidx.ui.test.sendSwipeUp
 import androidx.ui.text.FirstBaseline
 import androidx.ui.text.SoftwareKeyboardController
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.sp
-import androidx.ui.unit.toPx
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.atLeastOnce
@@ -82,8 +87,15 @@
     private val ExpectedPadding = 16.dp
     private val IconPadding = 12.dp
     private val ExpectedBaselineOffset = 20.dp
+    private val ExpectedLastBaselineOffset = 16.dp
     private val IconColorAlpha = 0.54f
 
+    private val LONG_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
+            "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam," +
+            " quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. " +
+            "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
+            "fugiat nulla pariatur."
+
     @get:Rule
     val testRule = createComposeRule().also {
         it.clockTestRule.pauseClock()
@@ -96,7 +108,8 @@
                 FilledTextField(
                     value = "input",
                     onValueChange = {},
-                    label = {}
+                    label = {},
+                    modifier = Modifier.preferredHeight(20.dp)
                 )
             }
             .assertHeightEqualsTo(ExpectedMinimumTextFieldHeight)
@@ -161,7 +174,7 @@
 
         // Click on (2, 2) which is Surface area and outside input area
         findByTag("textField").doGesture {
-            sendClick(PxPosition(2.ipx, 2.ipx))
+            sendClick(Offset(2f, 2f))
         }
 
         testRule.runOnIdleComposeWithDensity {
@@ -172,7 +185,7 @@
     @Test
     fun testLabelPosition_initial_withDefaultHeight() {
         val labelSize = Ref<IntPxSize>()
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
@@ -182,12 +195,14 @@
                         Text(
                             text = "label",
                             fontSize = 10.sp,
-                            modifier = Modifier.onPositioned {
-                                labelPosition.value = it.globalPosition
-                                labelSize.value = it.size
-                            }
+                            modifier = Modifier
+                                .onPositioned {
+                                    labelPosition.value = it.globalPosition
+                                    labelSize.value = it.size
+                                }
                         )
-                    }
+                    },
+                    modifier = Modifier.preferredHeight(56.dp)
                 )
             }
         }
@@ -212,7 +227,7 @@
     fun testLabelPosition_initial_withCustomHeight() {
         val height = 80.dp
         val labelSize = Ref<IntPxSize>()
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
@@ -247,7 +262,7 @@
     @Test
     fun testLabelPosition_whenFocused() {
         val labelSize = Ref<IntPxSize>()
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         val baseline = Ref<Float>()
         testRule.setMaterialContent {
             Box {
@@ -288,7 +303,7 @@
     @Test
     fun testLabelPosition_whenInput() {
         val labelSize = Ref<IntPxSize>()
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         val baseline = Ref<Float>()
         testRule.setMaterialContent {
             Box {
@@ -325,12 +340,14 @@
     @Test
     fun testPlaceholderPosition_withLabel() {
         val placeholderSize = Ref<IntPxSize>()
-        val placeholderPosition = Ref<PxPosition>()
+        val placeholderPosition = Ref<Offset>()
         val placeholderBaseline = Ref<Float>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
-                    modifier = Modifier.testTag("textField"),
+                    modifier = Modifier
+                        .preferredHeight(60.dp)
+                        .testTag("textField"),
                     value = "",
                     onValueChange = {},
                     label = { Text("label") },
@@ -358,16 +375,18 @@
             assertThat(placeholderPosition.value?.x).isEqualTo(
                 ExpectedPadding.toIntPx().value.toFloat()
             )
-            assertThat(placeholderBaseline.value).isEqualTo(
-                ExpectedBaselineOffset.toIntPx().value.toFloat() * 2
-            )
+            assertThat(placeholderBaseline.value)
+                .isEqualTo(
+                    60.dp.toIntPx().value.toFloat() -
+                            ExpectedLastBaselineOffset.toIntPx().value.toFloat()
+                )
         }
     }
 
     @Test
     fun testPlaceholderPosition_whenNoLabel() {
         val placeholderSize = Ref<IntPxSize>()
-        val placeholderPosition = Ref<PxPosition>()
+        val placeholderPosition = Ref<Offset>()
         val placeholderBaseline = Ref<Float>()
         val height = 60.dp
         testRule.setMaterialContent {
@@ -410,7 +429,7 @@
     @Test
     fun testNoPlaceholder_whenInputNotEmpty() {
         val placeholderSize = Ref<IntPxSize>()
-        val placeholderPosition = Ref<PxPosition>()
+        val placeholderPosition = Ref<Offset>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
@@ -463,9 +482,9 @@
         val textFieldHeight = 60.dp
         val textFieldWidth = 300.dp
         val size = 30.dp
-        val leadingPosition = Ref<PxPosition>()
+        val leadingPosition = Ref<Offset>()
         val leadingSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingSize = Ref<IntPxSize>()
 
         testRule.setMaterialContent {
@@ -512,7 +531,7 @@
     fun testLabelPositionX_initial_withTrailingAndLeading() {
         val height = 60.dp
         val iconSize = 30.dp
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
@@ -541,7 +560,7 @@
     @Test
     fun testLabelPositionX_initial_withEmptyTrailingAndLeading() {
         val height = 60.dp
-        val labelPosition = Ref<PxPosition>()
+        val labelPosition = Ref<Offset>()
         testRule.setMaterialContent {
             Box {
                 FilledTextField(
@@ -766,6 +785,127 @@
         }
     }
 
+    @Test
+    fun textField_scrollable_withLongInput() {
+        val scrollerPosition = TextFieldScrollerPosition()
+        testRule.setContent {
+            Stack {
+                TextFieldScroller(
+                    remember { scrollerPosition },
+                    Modifier.fillMaxWidth().preferredHeight(40.dp)
+                ) {
+                    TextField(
+                        value = TextFieldValue(LONG_TEXT),
+                        onValueChange = {}
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            assertThat(scrollerPosition.maximum).isLessThan(Float.POSITIVE_INFINITY)
+            assertThat(scrollerPosition.maximum).isGreaterThan(0f)
+        }
+    }
+
+    @Test
+    fun textField_notScrollable_withShortInput() {
+        val text = "text"
+        val scrollerPosition = TextFieldScrollerPosition()
+        testRule.setContent {
+            Stack {
+                TextFieldScroller(
+                    remember { scrollerPosition },
+                    Modifier.fillMaxWidth().preferredHeight(100.dp)
+                ) {
+                    TextField(
+                        value = TextFieldValue(text),
+                        onValueChange = {}
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            assertThat(scrollerPosition.maximum).isEqualTo(0f)
+        }
+    }
+
+    @Test
+    fun textField_scrolledAndClipped() {
+        val tag = "testTag"
+        val scrollerPosition = TextFieldScrollerPosition()
+
+        val parentSize = 200.ipx
+        val textFieldSize = 50.ipx
+
+        with(testRule.density) {
+            testRule.setContent {
+                Stack(Modifier
+                    .preferredSize(parentSize.toDp())
+                    .drawBackground(Color.White)
+                    .testTag(tag)
+                ) {
+                    TextFieldScroller(
+                        remember { scrollerPosition },
+                        Modifier.preferredSize(textFieldSize.toDp())
+                    ) {
+                        TextField(
+                            value = TextFieldValue(LONG_TEXT),
+                            onValueChange = {}
+                        )
+                    }
+                }
+            }
+        }
+
+        runOnIdleCompose {}
+
+        findByTag(tag)
+            .captureToBitmap()
+            .assertPixels(expectedSize = IntPxSize(parentSize, parentSize)) { position ->
+                if (position.x > textFieldSize && position.y > textFieldSize) Color.White else null
+            }
+    }
+
+    @Test
+    fun textField_swipe_whenLongInput() {
+        val tag = "testTag"
+        val scrollerPosition = TextFieldScrollerPosition()
+
+        testRule.setContent {
+            Stack {
+                TextFieldScroller(
+                    remember { scrollerPosition },
+                    Modifier.fillMaxWidth().preferredHeight(40.dp).testTag(tag)
+                ) {
+                    TextField(
+                        value = TextFieldValue(LONG_TEXT),
+                        onValueChange = {}
+                    )
+                }
+            }
+        }
+
+        runOnIdleCompose {
+            assertThat(scrollerPosition.current).isEqualTo(0f)
+        }
+
+        findByTag(tag)
+            .doGesture { sendSwipeDown() }
+
+        val firstSwipePosition = runOnIdleCompose {
+            scrollerPosition.current
+        }
+        assertThat(firstSwipePosition).isGreaterThan(0f)
+
+        findByTag(tag)
+            .doGesture { sendSwipeUp() }
+        runOnIdleCompose {
+            assertThat(scrollerPosition.current).isLessThan(firstSwipePosition)
+        }
+    }
+
     private fun clickAndAdvanceClock(tag: String, time: Long) {
         testRule.clockTestRule.pauseClock()
         findByTag(tag).doClick()
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/FloatingActionButtonTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/FloatingActionButtonTest.kt
index efc7277..5e25dac 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/FloatingActionButtonTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/FloatingActionButtonTest.kt
@@ -45,7 +45,6 @@
 import androidx.ui.unit.center
 import androidx.ui.unit.dp
 import androidx.ui.unit.height
-import androidx.ui.unit.toPx
 import androidx.ui.unit.width
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -298,7 +297,7 @@
 
                 assertWithinOnePixel(buttonBounds.center().y, iconBounds.center().y)
                 assertWithinOnePixel(buttonBounds.center().y, textBounds.center().y)
-                val halfPadding = 6.dp.toIntPx().toPx().value
+                val halfPadding = 6.dp.toIntPx().value.toFloat()
                 assertWithinOnePixel(
                     iconBounds.center().x + iconBounds.width / 2 + halfPadding,
                     textBounds.center().x - textBounds.width / 2 - halfPadding
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/ListItemTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/ListItemTest.kt
index d35fb91..5584105 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/ListItemTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/ListItemTest.kt
@@ -29,7 +29,7 @@
 import androidx.ui.test.createComposeRule
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import com.google.common.truth.Truth.assertThat
@@ -187,9 +187,9 @@
         val expectedLeftPadding = 16.dp
         val expectedRightPadding = 16.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
             Box {
@@ -224,9 +224,9 @@
         val expectedLeftPadding = 16.dp
         val expectedTextLeftPadding = 32.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textSize = Ref<IntPxSize>()
-        val iconPosition = Ref<PxPosition>()
+        val iconPosition = Ref<Offset>()
         val iconSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
             Box {
@@ -261,13 +261,13 @@
         val expectedTextBaseline = 28.dp
         val expectedSecondaryTextBaselineOffset = 20.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textBaseline = Ref<Float>()
         val textSize = Ref<IntPxSize>()
-        val secondaryTextPosition = Ref<PxPosition>()
+        val secondaryTextPosition = Ref<Offset>()
         val secondaryTextBaseline = Ref<Float>()
         val secondaryTextSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingBaseline = Ref<Float>()
         val trailingSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
@@ -325,13 +325,13 @@
         val expectedTextBaseline = 32.dp
         val expectedSecondaryTextBaselineOffset = 20.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textBaseline = Ref<Float>()
         val textSize = Ref<IntPxSize>()
-        val secondaryTextPosition = Ref<PxPosition>()
+        val secondaryTextPosition = Ref<Offset>()
         val secondaryTextBaseline = Ref<Float>()
         val secondaryTextSize = Ref<IntPxSize>()
-        val iconPosition = Ref<PxPosition>()
+        val iconPosition = Ref<Offset>()
         val iconSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
             Box {
@@ -391,15 +391,15 @@
         val expectedSecondaryTextBaselineOffset = 20.dp
         val expectedRightPadding = 16.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textBaseline = Ref<Float>()
         val textSize = Ref<IntPxSize>()
-        val secondaryTextPosition = Ref<PxPosition>()
+        val secondaryTextPosition = Ref<Offset>()
         val secondaryTextBaseline = Ref<Float>()
         val secondaryTextSize = Ref<IntPxSize>()
-        val iconPosition = Ref<PxPosition>()
+        val iconPosition = Ref<Offset>()
         val iconSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
             Box {
@@ -469,15 +469,15 @@
         val expectedSecondaryTextBaselineOffset = 20.dp
         val expectedRightPadding = 16.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textBaseline = Ref<Float>()
         val textSize = Ref<IntPxSize>()
-        val secondaryTextPosition = Ref<PxPosition>()
+        val secondaryTextPosition = Ref<Offset>()
         val secondaryTextBaseline = Ref<Float>()
         val secondaryTextSize = Ref<IntPxSize>()
-        val iconPosition = Ref<PxPosition>()
+        val iconPosition = Ref<Offset>()
         val iconSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingSize = Ref<IntPxSize>()
         composeTestRule.setMaterialContent {
             Box {
@@ -547,18 +547,18 @@
         val expectedSecondaryTextBaselineOffset = 20.dp
         val expectedRightPadding = 16.dp
 
-        val textPosition = Ref<PxPosition>()
+        val textPosition = Ref<Offset>()
         val textBaseline = Ref<Float>()
         val textSize = Ref<IntPxSize>()
-        val overlineTextPosition = Ref<PxPosition>()
+        val overlineTextPosition = Ref<Offset>()
         val overlineTextBaseline = Ref<Float>()
         val overlineTextSize = Ref<IntPxSize>()
-        val secondaryTextPosition = Ref<PxPosition>()
+        val secondaryTextPosition = Ref<Offset>()
         val secondaryTextBaseline = Ref<Float>()
         val secondaryTextSize = Ref<IntPxSize>()
-        val iconPosition = Ref<PxPosition>()
+        val iconPosition = Ref<Offset>()
         val iconSize = Ref<IntPxSize>()
-        val trailingPosition = Ref<PxPosition>()
+        val trailingPosition = Ref<Offset>()
         val trailingSize = Ref<IntPxSize>()
         val trailingBaseline = Ref<Float>()
         composeTestRule.setMaterialContent {
@@ -654,11 +654,11 @@
     private fun Dp.toIntPx() = (this.value * composeTestRule.density.density).roundToInt()
 
     private fun saveLayout(
-        coords: Ref<PxPosition>,
+        coords: Ref<Offset>,
         size: Ref<IntPxSize>,
         baseline: Ref<Float> = Ref()
     ): Modifier = Modifier.onPositioned { coordinates: LayoutCoordinates ->
-        coords.value = coordinates.localToGlobal(PxPosition.Origin)
+        coords.value = coordinates.localToGlobal(Offset.Zero)
         baseline.value = coordinates[FirstBaseline]?.value?.toFloat()?.let {
             it + coords.value!!.y
         }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/RippleTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/RippleTest.kt
deleted file mode 100644
index a4df9e8..0000000
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/RippleTest.kt
+++ /dev/null
@@ -1,509 +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.ui.material
-
-import android.os.Build
-import androidx.animation.AnimationClockObservable
-import androidx.animation.AnimationClockObserver
-import androidx.compose.Composable
-import androidx.compose.Providers
-import androidx.compose.getValue
-import androidx.compose.mutableStateOf
-import androidx.compose.setValue
-import androidx.test.filters.MediumTest
-import androidx.test.filters.SdkSuppress
-import androidx.ui.core.Modifier
-import androidx.ui.core.testTag
-import androidx.ui.foundation.Box
-import androidx.ui.foundation.ContentGravity
-import androidx.ui.foundation.clickable
-import androidx.ui.foundation.drawBackground
-import androidx.ui.geometry.Offset
-import androidx.ui.geometry.Size
-import androidx.ui.graphics.Color
-import androidx.ui.graphics.RectangleShape
-import androidx.ui.graphics.drawscope.DrawScope
-import androidx.ui.graphics.drawscope.clipRect
-import androidx.ui.layout.Row
-import androidx.ui.layout.padding
-import androidx.ui.layout.preferredSize
-import androidx.ui.material.ripple.RippleEffect
-import androidx.ui.material.ripple.RippleEffectFactory
-import androidx.ui.material.ripple.RippleTheme
-import androidx.ui.material.ripple.RippleThemeAmbient
-import androidx.ui.material.ripple.ripple
-import androidx.ui.test.assertShape
-import androidx.ui.test.captureToBitmap
-import androidx.ui.test.createComposeRule
-import androidx.ui.test.doClick
-import androidx.ui.test.findByTag
-import androidx.ui.test.runOnIdleCompose
-import androidx.ui.test.runOnUiThread
-import androidx.ui.unit.Density
-import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.PxSize
-import androidx.ui.unit.dp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-
-@MediumTest
-@RunWith(JUnit4::class)
-class RippleTest {
-
-    private val contentTag = "ripple"
-
-    @get:Rule
-    val composeTestRule = createComposeRule()
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    @Test
-    fun rippleDrawsCorrectly() {
-        composeTestRule.setMaterialContent {
-            DrawRectRippleCallback {
-                Box(
-                    modifier = Modifier.drawBackground(Color.Blue).testTag(contentTag),
-                    gravity = ContentGravity.Center
-                ) {
-                    Box(
-                        Modifier.preferredSize(10.dp)
-                            .ripple()
-                    )
-                }
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        val bitmap = findByTag(contentTag).captureToBitmap()
-        with(composeTestRule.density) {
-            bitmap.assertShape(
-                density = composeTestRule.density,
-                backgroundColor = Color.Blue,
-                shape = RectangleShape,
-                shapeSizeX = 10.dp.toPx(),
-                shapeSizeY = 10.dp.toPx(),
-                shapeColor = Color.Red
-            )
-        }
-    }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    @Test
-    fun rippleUsesCorrectSize() {
-        composeTestRule.setMaterialContent {
-            DrawRectRippleCallback {
-                Box(
-                    modifier = Modifier.drawBackground(Color.Blue).testTag(contentTag),
-                    gravity = ContentGravity.Center
-                ) {
-                    Box(
-                        Modifier.preferredSize(30.dp)
-                            .padding(5.dp)
-                            .ripple()
-                            // this padding should not affect the size of the ripple
-                            .padding(5.dp)
-                    )
-                }
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        val bitmap = findByTag(contentTag).captureToBitmap()
-        with(composeTestRule.density) {
-            bitmap.assertShape(
-                density = composeTestRule.density,
-                backgroundColor = Color.Blue,
-                shape = RectangleShape,
-                shapeSizeX = 20.dp.toPx(),
-                shapeSizeY = 20.dp.toPx(),
-                shapeColor = Color.Red
-            )
-        }
-    }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    @Test
-    fun unboundedIsNotClipped() {
-        composeTestRule.setMaterialContent {
-            DrawRectRippleCallback {
-                Box(
-                    modifier = Modifier.drawBackground(Color.Blue).testTag(contentTag),
-                    gravity = ContentGravity.Center
-                ) {
-                    Box(Modifier.preferredSize(10.dp).ripple(bounded = false))
-                }
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        val bitmap = findByTag(contentTag).captureToBitmap()
-        bitmap.assertShape(
-            density = composeTestRule.density,
-            backgroundColor = Color.Red,
-            shape = RectangleShape,
-            shapeSizeX = 0.0f,
-            shapeSizeY = 0.0f,
-            shapeColor = Color.Red
-        )
-    }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    @Test
-    fun rippleDrawnAfterContent() {
-        composeTestRule.setMaterialContent {
-            DrawRectRippleCallback {
-                Box(
-                    modifier = Modifier.drawBackground(Color.Blue).testTag(contentTag),
-                    gravity = ContentGravity.Center
-                ) {
-                    Box(
-                        Modifier.preferredSize(10.dp)
-                            .ripple()
-                            .drawBackground(Color.Blue)
-                    )
-                }
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        val bitmap = findByTag(contentTag).captureToBitmap()
-        with(composeTestRule.density) {
-            bitmap.assertShape(
-                density = composeTestRule.density,
-                backgroundColor = Color.Blue,
-                shape = RectangleShape,
-                shapeSizeX = 10.0.dp.toPx(),
-                shapeSizeY = 10.0.dp.toPx(),
-                shapeColor = Color.Red
-            )
-        }
-    }
-
-    @Test
-    fun twoEffectsDrawnAndDisposedCorrectly() {
-        val drawLatch = CountDownLatch(2)
-        val disposeLatch = CountDownLatch(2)
-        var emit by mutableStateOf(true)
-
-        composeTestRule.setMaterialContent {
-            RippleCallback(
-                onDraw = { drawLatch.countDown() },
-                onDispose = { disposeLatch.countDown() }
-            ) {
-                Card {
-                    if (emit) {
-                        Row {
-                            RippleButton(modifier = Modifier.testTag(contentTag))
-                        }
-                    }
-                }
-            }
-        }
-
-        // create two effects
-        findByTag(contentTag)
-            .doClick()
-        findByTag(contentTag)
-            .doClick()
-
-        // wait for drawEffect to be called
-        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
-
-        runOnUiThread { emit = false }
-
-        // wait for dispose to be called
-        assertTrue(disposeLatch.await(1, TimeUnit.SECONDS))
-    }
-
-    @Test
-    fun animationIsDisposedCorrectly() {
-        var emit by mutableStateOf(true)
-        var effectCreated = false
-        var rippleAnimationTime = 0L
-
-        val factory = object : RippleEffectFactory {
-            override fun create(
-                size: PxSize,
-                startPosition: PxPosition,
-                density: Density,
-                radius: Dp?,
-                clipped: Boolean,
-                clock: AnimationClockObservable,
-                onAnimationFinished: (RippleEffect) -> Unit
-            ): RippleEffect {
-                clock.subscribe(object : AnimationClockObserver {
-                    override fun onAnimationFrame(frameTimeMillis: Long) {
-                        rippleAnimationTime = frameTimeMillis
-                    }
-                })
-                effectCreated = true
-                return object : RippleEffect {
-                    override fun DrawScope.draw(color: Color) {}
-                    override fun finish(canceled: Boolean) {}
-                }
-            }
-        }
-
-        composeTestRule.clockTestRule.pauseClock()
-
-        composeTestRule.setMaterialContent {
-            Providers(
-                RippleThemeAmbient provides RippleThemeAmbient.current.copy(
-                    factory = factory
-                )
-            ) {
-                Card {
-                    if (emit) {
-                        Row {
-                            RippleButton(modifier = Modifier.testTag(contentTag))
-                        }
-                    }
-                }
-            }
-        }
-
-        // create an effect
-        findByTag(contentTag)
-            .doClick()
-
-        // wait for drawEffect to be called
-        assertThat(effectCreated).isTrue()
-        assertThat(rippleAnimationTime).isEqualTo(0)
-
-        // we got a first frame
-        composeTestRule.clockTestRule.advanceClock(100)
-        assertThat(rippleAnimationTime).isNotEqualTo(0)
-        var prevValue = rippleAnimationTime
-
-        // animation is working and we are getting the next frames
-        composeTestRule.clockTestRule.advanceClock(100)
-        assertThat(rippleAnimationTime).isGreaterThan(prevValue)
-        prevValue = rippleAnimationTime
-
-        runOnIdleCompose {
-            emit = false
-        }
-
-        runOnIdleCompose {
-            // wait for the dispose to be applied
-        }
-
-        composeTestRule.clockTestRule.advanceClock(100)
-        // asserts our animation is disposed and not reacting on a new timestamp
-        assertThat(rippleAnimationTime).isEqualTo(prevValue)
-    }
-
-    @Test
-    fun rippleColorAndOpacityAreTakenFromTheme() {
-        val drawLatch = CountDownLatch(1)
-        val color = Color.Yellow
-        val opacity = 0.2f
-        composeTestRule.setMaterialContent {
-            RippleCallback(
-                defaultColor = { color },
-                opacityCallback = { opacity },
-                onDraw = { actualColor ->
-                    assertEquals(color.copy(alpha = opacity), actualColor)
-                    drawLatch.countDown()
-                }
-            ) {
-                RippleButton(modifier = Modifier.testTag(contentTag))
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        // wait for drawEffect to be called
-        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
-    }
-
-    @Test
-    fun rippleOpacityIsTakenFromTheme() {
-        val drawLatch = CountDownLatch(1)
-        val color = Color.Green
-        val opacity = 0.2f
-        composeTestRule.setMaterialContent {
-            RippleCallback(
-                opacityCallback = { opacity },
-                onDraw = { actualColor ->
-                    assertEquals(color.copy(alpha = opacity), actualColor)
-                    drawLatch.countDown()
-                }
-            ) {
-                RippleButton(modifier = Modifier.testTag(contentTag), color = color)
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        // wait for drawEffect to be called
-        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
-    }
-
-    @Test
-    fun disabledRippleDoesntCreateEffects() {
-        val createdLatch = CountDownLatch(1)
-
-        composeTestRule.setMaterialContent {
-            RippleCallback(
-                onEffectCreated = { createdLatch.countDown() }
-            ) {
-                Card {
-                    RippleButton(modifier = Modifier.testTag(contentTag), enabled = false)
-                }
-            }
-        }
-
-        // create two effects
-        findByTag(contentTag)
-            .doClick()
-
-        // assert no effects has been created
-        assertFalse(createdLatch.await(500, TimeUnit.MILLISECONDS))
-    }
-
-    @Test
-    fun rippleColorChangeWhileAnimatingAppliedCorrectly() {
-        var drawLatch = CountDownLatch(1)
-        var actualColor = Color.Transparent
-        var colorState by mutableStateOf(Color.Yellow)
-        composeTestRule.setMaterialContent {
-            RippleCallback(
-                defaultColor = { colorState },
-                onDraw = { color ->
-                    actualColor = color
-                    drawLatch.countDown()
-                }
-            ) {
-                RippleButton(modifier = Modifier.testTag(contentTag))
-            }
-        }
-
-        findByTag(contentTag)
-            .doClick()
-
-        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
-        assertEquals(Color.Yellow, actualColor)
-
-        drawLatch = CountDownLatch(1)
-        runOnUiThread {
-            colorState = Color.Green
-        }
-
-        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
-        assertEquals(Color.Green, actualColor)
-    }
-
-    @Composable
-    private fun RippleButton(
-        modifier: Modifier = Modifier,
-        size: Dp = 10.dp,
-        color: Color = Color.Unset,
-        enabled: Boolean = true
-    ) {
-        Box(modifier
-            .ripple(bounded = false, color = color, enabled = enabled)
-            .clickable(indication = null) {}) {
-            Box(Modifier.preferredSize(size))
-        }
-    }
-
-    @Composable
-    fun DrawRectRippleCallback(children: @Composable () -> Unit) {
-        RippleCallback(
-            onDraw = {
-                drawRect(
-                    Color.Red,
-                    topLeft = Offset(-100000f, -100000f),
-                    size = Size(200000f, 200000f)
-                )
-            },
-            children = children
-        )
-    }
-
-    @Composable
-    private fun RippleCallback(
-        onDraw: DrawScope.(Color) -> Unit = { _ -> },
-        onDispose: () -> Unit = {},
-        onEffectCreated: () -> Unit = {},
-        defaultColor: @Composable () -> Color = { Color(0) },
-        opacityCallback: @Composable () -> Float = { 1f },
-        children: @Composable () -> Unit
-    ) {
-        val theme = RippleTheme(
-            testRippleEffect(onDraw, onDispose, onEffectCreated),
-            defaultColor,
-            opacityCallback
-        )
-        Providers(RippleThemeAmbient provides theme, children = children)
-    }
-
-    private fun testRippleEffect(
-        onDraw: DrawScope.(Color) -> Unit,
-        onDispose: () -> Unit,
-        onEffectCreated: () -> Unit
-    ): RippleEffectFactory =
-        object : RippleEffectFactory {
-            override fun create(
-                size: PxSize,
-                startPosition: PxPosition,
-                density: Density,
-                radius: Dp?,
-                clipped: Boolean,
-                clock: AnimationClockObservable,
-                onAnimationFinished: (RippleEffect) -> Unit
-            ): RippleEffect {
-                onEffectCreated()
-                return object : RippleEffect {
-                    override fun DrawScope.draw(color: Color) {
-                        if (clipped) {
-                            clipRect {
-                                this@draw.onDraw(color)
-                            }
-                        } else {
-                            this@draw.onDraw(color)
-                        }
-                    }
-
-                    override fun finish(canceled: Boolean) {
-                    }
-
-                    override fun dispose() {
-                        onDispose()
-                    }
-                }
-            }
-        }
-}
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
index 96945bc..8a5678a 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
@@ -52,9 +52,8 @@
 import androidx.ui.test.sendSwipeLeft
 import androidx.ui.test.sendSwipeRight
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
-import androidx.ui.unit.px
 import androidx.ui.unit.toPxSize
 import androidx.ui.unit.toSize
 import androidx.ui.unit.width
@@ -89,8 +88,8 @@
 
     @Test
     fun scaffold_onlyContent_stackSlot() {
-        lateinit var child1: PxPosition
-        lateinit var child2: PxPosition
+        var child1: Offset = Offset.Zero
+        var child2: Offset = Offset.Zero
         composeTestRule.setMaterialContent {
             Scaffold {
                 Text("One",
@@ -107,15 +106,15 @@
 
     @Test
     fun scaffold_AppbarAndContent_inColumn() {
-        lateinit var appbarPosition: PxPosition
+        var appbarPosition: Offset = Offset.Zero
         lateinit var appbarSize: IntPxSize
-        lateinit var contentPosition: PxPosition
+        var contentPosition: Offset = Offset.Zero
         composeTestRule.setMaterialContent {
             Scaffold(
                 topBar = {
                     Box(Modifier
                         .onPositioned { positioned: LayoutCoordinates ->
-                            appbarPosition = positioned.localToGlobal(PxPosition.Origin)
+                            appbarPosition = positioned.localToGlobal(Offset.Zero)
                             appbarSize = positioned.size
                         }
                         .fillMaxWidth()
@@ -125,7 +124,7 @@
                 }
             ) {
                 Box(Modifier
-                    .onPositioned { contentPosition = it.localToGlobal(PxPosition.Origin) }
+                    .onPositioned { contentPosition = it.localToGlobal(Offset.Zero) }
                     .fillMaxWidth()
                     .preferredHeight(50.dp)
                     .drawBackground(Color.Blue)
@@ -138,9 +137,9 @@
 
     @Test
     fun scaffold_bottomBarAndContent_inStack() {
-        lateinit var appbarPosition: PxPosition
+        var appbarPosition: Offset = Offset.Zero
         lateinit var appbarSize: IntPxSize
-        lateinit var contentPosition: PxPosition
+        var contentPosition: Offset = Offset.Zero
         lateinit var contentSize: IntPxSize
         composeTestRule.setMaterialContent {
             Scaffold(
@@ -175,7 +174,7 @@
     @Test
     @Ignore("unignore once animation sync is ready (b/147291885)")
     fun scaffold_drawer_gestures() {
-        lateinit var drawerChildPosition: PxPosition
+        var drawerChildPosition: Offset = Offset.Zero
         val scaffoldState = ScaffoldState(isDrawerGesturesEnabled = false)
         composeTestRule.setMaterialContent {
             Semantics(properties = { testTag = scaffoldTag }) {
@@ -228,7 +227,7 @@
     @Test
     @Ignore("unignore once animation sync is ready (b/147291885)")
     fun scaffold_drawer_manualControl() {
-        lateinit var drawerChildPosition: PxPosition
+        var drawerChildPosition: Offset = Offset.Zero
         val scaffoldState = ScaffoldState()
         composeTestRule.setMaterialContent {
             Semantics(properties = { testTag = scaffoldTag }) {
@@ -267,9 +266,9 @@
 
     @Test
     fun scaffold_centerDockedFab_position() {
-        lateinit var fabPosition: PxPosition
+        var fabPosition: Offset = Offset.Zero
         lateinit var fabSize: IntPxSize
-        lateinit var bottomBarPosition: PxPosition
+        var bottomBarPosition: Offset = Offset.Zero
         composeTestRule.setContent {
             Scaffold(
                 floatingActionButton = {
@@ -305,9 +304,9 @@
 
     @Test
     fun scaffold_endDockedFab_position() {
-        lateinit var fabPosition: PxPosition
+        var fabPosition: Offset = Offset.Zero
         lateinit var fabSize: IntPxSize
-        lateinit var bottomBarPosition: PxPosition
+        var bottomBarPosition: Offset = Offset.Zero
         composeTestRule.setContent {
             Scaffold(
                 floatingActionButton = {
@@ -548,7 +547,7 @@
         }
         runOnIdleCompose {
             assertThat(geometry.bottomBarBounds?.toSize()).isEqualTo(bottomBarSize.toPxSize())
-            assertThat(geometry.bottomBarBounds?.width).isNotEqualTo(0.px)
+            assertThat(geometry.bottomBarBounds?.width).isNotEqualTo(0f)
         }
     }
 }
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
index 246686d..b84cefa 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
@@ -42,7 +42,7 @@
 import androidx.ui.test.findByTag
 import androidx.ui.test.findByText
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import com.google.common.truth.Truth.assertThat
@@ -164,7 +164,7 @@
         ) {
             with(composeTestRule.density) {
                 val buttonTextPos =
-                    localSnackCoords.childToLocal(localButtonTextCoords, PxPosition.Origin)
+                    localSnackCoords.childToLocal(localButtonTextCoords, Offset.Zero)
                 assertThat(localTextCoords[FirstBaseline]).isNotEqualTo(IntPx.Zero)
                 assertThat(localButtonTextCoords[FirstBaseline]).isNotEqualTo(IntPx.Zero)
                 assertThat(
@@ -246,7 +246,7 @@
         if (localTextCoords != null && localButtonCoords != null && localSnackCoords != null) {
             with(composeTestRule.density) {
                 val buttonPositionInSnack =
-                    localSnackCoords.childToLocal(localButtonCoords, PxPosition.Origin)
+                    localSnackCoords.childToLocal(localButtonCoords, Offset.Zero)
                 val buttonCenter =
                     buttonPositionInSnack.y.roundToInt() +
                             (localButtonCoords.size.height / 2).value.toFloat()
@@ -303,9 +303,9 @@
         if (localTextCoords != null && localButtonCoords != null && localSnackCoords != null) {
             with(composeTestRule.density) {
                 val buttonPositionInSnack =
-                    localSnackCoords.childToLocal(localButtonCoords, PxPosition.Origin)
+                    localSnackCoords.childToLocal(localButtonCoords, Offset.Zero)
                 val textPositionInSnack =
-                    localSnackCoords.childToLocal(localTextCoords, PxPosition.Origin)
+                    localSnackCoords.childToLocal(localTextCoords, Offset.Zero)
 
                 assertThat(
                     textPositionInSnack.y.roundToInt().ipx + localTextCoords[FirstBaseline]!!
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
index faf7797..043f69e 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
@@ -45,9 +45,8 @@
 import androidx.ui.test.findAll
 import androidx.ui.test.isInMutuallyExclusiveGroup
 import androidx.ui.test.runOnIdleCompose
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
-import androidx.ui.unit.toPx
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -146,11 +145,11 @@
             val tabRowWidth = tabRowCoords.size.width
             val tabRowHeight = tabRowCoords.size.height
 
-            val indicatorPositionX = indicatorCoords.localToGlobal(PxPosition.Origin).x
+            val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
             val expectedPositionX = 0.dp.toPx()
             assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
 
-            val indicatorPositionY = indicatorCoords.localToGlobal(PxPosition.Origin).y
+            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
             val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).value.toFloat()
             assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
 
@@ -164,11 +163,11 @@
         // should be in the middle of the TabRow
         runOnIdleCompose {
             with(composeTestRule.density) {
-                val indicatorPositionX = indicatorCoords.localToGlobal(PxPosition.Origin).x
+                val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
                 val expectedPositionX = (tabRowWidth / 2).value.toFloat()
                 assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
 
-                val indicatorPositionY = indicatorCoords.localToGlobal(PxPosition.Origin).y
+                val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
                 val expectedPositionY =
                     (tabRowHeight - indicatorHeight.toIntPx()).value.toFloat()
                 assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
@@ -196,7 +195,7 @@
                         text = {
                             Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
                                 textCoords = coords
-                                textBaseline = coords[LastBaseline]!!.toPx().value
+                                textBaseline = coords[LastBaseline]!!.value.toFloat()
                             })
                         },
                         selected = state == index,
@@ -210,13 +209,13 @@
             val expectedBaseline = 18.dp
             val indicatorHeight = 2.dp
             val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toPx()
+                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).value.toFloat()
 
             val tabRowHeight = tabRowCoords.size.height
 
-            val textPositionY = textCoords.localToGlobal(PxPosition.Origin).y
+            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
             val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toPx() - expectedBaselineDistance).value
+            val expectedPositionY = (tabRowHeight.value.toFloat() - expectedBaselineDistance)
             assertThat(baselinePositionY).isEqualTo(expectedPositionY)
         }
     }
@@ -241,7 +240,7 @@
                         text = {
                             Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
                                 textCoords = coords
-                                textBaseline = coords[LastBaseline]!!.toPx().value
+                                textBaseline = coords[LastBaseline]!!.value.toFloat()
                             })
                         },
                         icon = { Icon(Icons.Filled.Favorite) },
@@ -256,13 +255,13 @@
             val expectedBaseline = 14.dp
             val indicatorHeight = 2.dp
             val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toPx()
+                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).value.toFloat()
 
             val tabRowHeight = tabRowCoords.size.height
 
-            val textPositionY = textCoords.localToGlobal(PxPosition.Origin).y
+            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
             val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toPx() - expectedBaselineDistance).value
+            val expectedPositionY = (tabRowHeight.value.toFloat() - expectedBaselineDistance)
             assertThat(baselinePositionY).isEqualTo(expectedPositionY)
         }
     }
@@ -287,7 +286,7 @@
                         text = {
                             Text(text, Modifier.preferredWidth(100.dp).onPositioned { coords ->
                                 textCoords = coords
-                                textBaseline = coords[LastBaseline]!!.toPx().value
+                                textBaseline = coords[LastBaseline]!!.value.toFloat()
                             }, maxLines = 2)
                         },
                         selected = state == index,
@@ -301,13 +300,13 @@
             val expectedBaseline = 10.dp
             val indicatorHeight = 2.dp
             val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toPx()
+                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).value.toFloat()
 
             val tabRowHeight = tabRowCoords.size.height
 
-            val textPositionY = textCoords.localToGlobal(PxPosition.Origin).y
+            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
             val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toPx() - expectedBaselineDistance).value
+            val expectedPositionY = (tabRowHeight.value.toFloat() - expectedBaselineDistance)
             assertThat(baselinePositionY).isEqualTo(expectedPositionY)
         }
     }
@@ -356,12 +355,12 @@
             val tabRowHeight = tabRowCoords.size.height
 
             // Indicator should be placed in the bottom left of the first tab
-            val indicatorPositionX = indicatorCoords.localToGlobal(PxPosition.Origin).x
+            val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
             // Tabs in a scrollable tab row are offset 52.dp from each end
             val expectedPositionX = scrollableTabRowOffset.toIntPx().value.toFloat()
             assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
 
-            val indicatorPositionY = indicatorCoords.localToGlobal(PxPosition.Origin).y
+            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
             val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).value.toFloat()
             assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
 
@@ -374,12 +373,12 @@
         // Indicator should now be placed in the bottom left of the second tab, so its x coordinate
         // should be in the middle of the TabRow
         composeTestRule.runOnIdleComposeWithDensity {
-            val indicatorPositionX = indicatorCoords.localToGlobal(PxPosition.Origin).x
+            val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
             val expectedPositionX =
                 (scrollableTabRowOffset + minimumTabWidth).toIntPx().value.toFloat()
             assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
 
-            val indicatorPositionY = indicatorCoords.localToGlobal(PxPosition.Origin).y
+            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
             val expectedPositionY =
                 (tabRowHeight - indicatorHeight.toIntPx()).value.toFloat()
             assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
new file mode 100644
index 0000000..d52810d
--- /dev/null
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
@@ -0,0 +1,680 @@
+/*
+ * 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.material.ripple
+
+import android.os.Build
+import androidx.compose.Composable
+import androidx.compose.Providers
+import androidx.compose.emptyContent
+import androidx.compose.getValue
+import androidx.compose.mutableStateOf
+import androidx.compose.setValue
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.test.screenshot.assertAgainstGolden
+import androidx.ui.core.Modifier
+import androidx.ui.core.semantics.semantics
+import androidx.ui.core.testTag
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.ContentGravity
+import androidx.ui.foundation.Interaction
+import androidx.ui.foundation.InteractionState
+import androidx.ui.foundation.indication
+import androidx.ui.foundation.shape.corner.RoundedCornerShape
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.compositeOver
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.padding
+import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.preferredWidth
+import androidx.ui.material.GOLDEN_MATERIAL
+import androidx.ui.material.MaterialTheme
+import androidx.ui.material.Surface
+import androidx.ui.material.darkColorPalette
+import androidx.ui.material.lightColorPalette
+import androidx.ui.test.ComposeTestRule
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.findByTag
+import androidx.ui.test.runOnUiThread
+import androidx.ui.test.waitForIdle
+import androidx.ui.unit.dp
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@LargeTest
+@RunWith(JUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class RippleIndicationTest {
+
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL)
+
+    @Test
+    fun bounded_lightTheme_highLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_bounded_light_highluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.24f)
+        )
+    }
+
+    @Test
+    fun bounded_lightTheme_highLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_bounded_light_highluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.16f)
+        )
+    }
+
+    @Test
+    fun bounded_lightTheme_lowLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_bounded_light_lowluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.12f)
+        )
+    }
+
+    @Test
+    fun bounded_lightTheme_lowLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_bounded_light_lowluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun bounded_darkTheme_highLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_bounded_dark_highluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.10f)
+        )
+    }
+
+    @Test
+    fun bounded_darkTheme_highLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_bounded_dark_highluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun bounded_darkTheme_lowLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_bounded_dark_lowluminance_pressed",
+            // Low luminance content in dark theme should use a white ripple by default
+            calculateResultingRippleColor(Color.White, rippleOpacity = 0.10f)
+        )
+    }
+
+    @Test
+    fun bounded_darkTheme_lowLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = true,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_bounded_dark_lowluminance_dragged",
+            // Low luminance content in dark theme should use a white ripple by default
+            calculateResultingRippleColor(Color.White, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun unbounded_lightTheme_highLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_unbounded_light_highluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.24f)
+        )
+    }
+
+    @Test
+    fun unbounded_lightTheme_highLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_unbounded_light_highluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.16f)
+        )
+    }
+
+    @Test
+    fun unbounded_lightTheme_lowLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_unbounded_light_lowluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.12f)
+        )
+    }
+
+    @Test
+    fun unbounded_lightTheme_lowLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = true,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_unbounded_light_lowluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun unbounded_darkTheme_highLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_unbounded_dark_highluminance_pressed",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.10f)
+        )
+    }
+
+    @Test
+    fun unbounded_darkTheme_highLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.White
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_unbounded_dark_highluminance_dragged",
+            calculateResultingRippleColor(contentColor, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun unbounded_darkTheme_lowLuminance_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_unbounded_dark_lowluminance_pressed",
+            // Low luminance content in dark theme should use a white ripple by default
+            calculateResultingRippleColor(Color.White, rippleOpacity = 0.10f)
+        )
+    }
+
+    @Test
+    fun unbounded_darkTheme_lowLuminance_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        composeTestRule.setRippleContent(
+            interactionState = interactionState,
+            bounded = false,
+            lightTheme = false,
+            contentColor = contentColor
+        )
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_unbounded_dark_lowluminance_dragged",
+            // Low luminance content in dark theme should use a white ripple by default
+            calculateResultingRippleColor(Color.White, rippleOpacity = 0.08f)
+        )
+    }
+
+    @Test
+    fun customRippleTheme_pressed() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        val rippleColor = Color.Red
+        val rippleAlpha = 0.5f
+
+        val rippleTheme = object : RippleTheme {
+            @Composable
+            override fun defaultColor() = rippleColor
+
+            @Composable
+            override fun rippleOpacity() = object : RippleOpacity {
+                override fun opacityForInteraction(interaction: Interaction) = rippleAlpha
+            }
+        }
+
+        composeTestRule.setContent {
+            Providers(RippleThemeAmbient provides rippleTheme) {
+                MaterialTheme {
+                    Surface(contentColor = contentColor) {
+                        Box(Modifier.fillMaxSize(), gravity = ContentGravity.Center) {
+                            RippleBox(interactionState, RippleIndication())
+                        }
+                    }
+                }
+            }
+        }
+
+        val expectedColor = calculateResultingRippleColor(rippleColor, rippleOpacity = rippleAlpha)
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Pressed,
+            "rippleindication_customtheme_pressed",
+            expectedColor
+        )
+    }
+
+    @Test
+    fun customRippleTheme_dragged() {
+        val interactionState = InteractionState()
+
+        val contentColor = Color.Black
+
+        val rippleColor = Color.Red
+        val rippleAlpha = 0.5f
+
+        val rippleTheme = object : RippleTheme {
+            @Composable
+            override fun defaultColor() = rippleColor
+
+            @Composable
+            override fun rippleOpacity() = object : RippleOpacity {
+                override fun opacityForInteraction(interaction: Interaction) = rippleAlpha
+            }
+        }
+
+        composeTestRule.setContent {
+            Providers(RippleThemeAmbient provides rippleTheme) {
+                MaterialTheme {
+                    Surface(contentColor = contentColor) {
+                        Box(Modifier.fillMaxSize(), gravity = ContentGravity.Center) {
+                            RippleBox(interactionState, RippleIndication())
+                        }
+                    }
+                }
+            }
+        }
+
+        val expectedColor = calculateResultingRippleColor(rippleColor, rippleOpacity = rippleAlpha)
+
+        assertRippleMatches(
+            interactionState,
+            Interaction.Dragged,
+            "rippleindication_customtheme_dragged",
+            expectedColor
+        )
+    }
+
+    @Test
+    fun themeChangeDuringRipple() {
+        val interactionState = InteractionState()
+
+        fun createRippleTheme(color: Color, alpha: Float) = object : RippleTheme {
+            @Composable
+            override fun defaultColor() = color
+
+            @Composable
+            override fun rippleOpacity() = object : RippleOpacity {
+                override fun opacityForInteraction(interaction: Interaction) = alpha
+            }
+        }
+
+        val initialColor = Color.Red
+        val initialAlpha = 0.5f
+
+        var rippleTheme by mutableStateOf(createRippleTheme(initialColor, initialAlpha))
+
+        composeTestRule.setContent {
+            Providers(RippleThemeAmbient provides rippleTheme) {
+                MaterialTheme {
+                    Surface(contentColor = Color.Black) {
+                        Box(Modifier.fillMaxSize(), gravity = ContentGravity.Center) {
+                            RippleBox(interactionState, RippleIndication())
+                        }
+                    }
+                }
+            }
+        }
+
+        runOnUiThread {
+            interactionState.addInteraction(Interaction.Pressed, Offset(10f, 10f))
+        }
+
+        with(findByTag(Tag)) {
+            val centerPixel = captureToBitmap()
+                .run {
+                    getPixel(width / 2, height / 2)
+                }
+
+            val expectedColor =
+                calculateResultingRippleColor(initialColor, rippleOpacity = initialAlpha)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+
+        val newColor = Color.Green
+        val newAlpha = 0.2f
+
+        runOnUiThread {
+            rippleTheme = createRippleTheme(newColor, newAlpha)
+        }
+
+        with(findByTag(Tag)) {
+            val centerPixel = captureToBitmap()
+                .run {
+                    getPixel(width / 2, height / 2)
+                }
+
+            val expectedColor =
+                calculateResultingRippleColor(newColor, rippleOpacity = newAlpha)
+
+            Truth.assertThat(Color(centerPixel)).isEqualTo(expectedColor)
+        }
+    }
+
+    /**
+     * Asserts that the ripple matches the screenshot with identifier [goldenIdentifier], and
+     * that the resultant color of the ripple on screen matches [expectedCenterPixelColor].
+     *
+     * @param interactionState the [InteractionState] driving the ripple
+     * @param interaction the [Interaction] to assert for
+     * @param goldenIdentifier the identifier for the corresponding screenshot
+     * @param expectedCenterPixelColor the expected color for the pixel at the center of the
+     * [RippleBox]
+     */
+    private fun assertRippleMatches(
+        interactionState: InteractionState,
+        interaction: Interaction,
+        goldenIdentifier: String,
+        expectedCenterPixelColor: Color
+    ) {
+        composeTestRule.clockTestRule.pauseClock()
+
+        // Start ripple
+        runOnUiThread {
+            if (interaction is Interaction.Pressed) {
+                interactionState.addInteraction(interaction, Offset(10f, 10f))
+            } else {
+                interactionState.addInteraction(interaction)
+            }
+        }
+
+        // Advance to somewhere in the middle of the animation for a ripple, or at the end of a
+        // state layer transition
+        waitForIdle()
+        composeTestRule.clockTestRule.advanceClock(50)
+
+        // Capture and compare screenshots
+        findByTag(Tag)
+            .captureToBitmap()
+            .assertAgainstGolden(screenshotRule, goldenIdentifier)
+
+        // Advance until after the end of the ripple animation, so we have a stable final opacity
+        waitForIdle()
+        composeTestRule.clockTestRule.advanceClock(50)
+        waitForIdle()
+
+        // Compare expected and actual pixel color
+        val centerPixel = findByTag(Tag)
+            .captureToBitmap()
+            .run {
+                getPixel(width / 2, height / 2)
+            }
+
+        Truth.assertThat(Color(centerPixel)).isEqualTo(expectedCenterPixelColor)
+    }
+}
+
+/**
+ * Generic Button like component that allows injecting a [RippleIndication] and also includes
+ * padding around the rippled surface, so screenshots will include some dead space for clarity.
+ *
+ * @param interactionState the [InteractionState] that is used to drive the ripple state
+ * @param rippleIndication [RippleIndication] placed inside the surface
+ */
+@Composable
+private fun RippleBox(interactionState: InteractionState, rippleIndication: RippleIndication) {
+    Box(Modifier.semantics(mergeAllDescendants = true).testTag(Tag)) {
+        Surface(
+            Modifier.padding(25.dp),
+            color = RippleBoxBackgroundColor, shape = RoundedCornerShape(20)
+        ) {
+            Box(
+                Modifier.preferredWidth(80.dp).preferredHeight(50.dp).indication(
+                    interactionState = interactionState,
+                    indication = rippleIndication
+                ),
+                children = emptyContent()
+            )
+        }
+    }
+}
+
+/**
+ * Sets the content to a [RippleBox] with a [MaterialTheme] and surrounding [Surface]
+ *
+ * @param interactionState [InteractionState] used to drive the ripple inside the [RippleBox]
+ * @param bounded whether the ripple inside the [RippleBox] is bounded
+ * @param lightTheme whether the theme is light or dark
+ * @param contentColor the contentColor that will be used for the ripple color
+ */
+private fun ComposeTestRule.setRippleContent(
+    interactionState: InteractionState,
+    bounded: Boolean,
+    lightTheme: Boolean,
+    contentColor: Color
+) {
+    setContent {
+        val colorPalette = if (lightTheme) lightColorPalette() else darkColorPalette()
+
+        MaterialTheme(colorPalette) {
+            Surface(contentColor = contentColor) {
+                Box(Modifier.fillMaxSize(), gravity = ContentGravity.Center) {
+                    RippleBox(interactionState, RippleIndication(bounded))
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Blends ([contentColor] with [rippleOpacity]) on top of [RippleBoxBackgroundColor] to provide
+ * the resulting RGB color that can be used for pixel comparison.
+ */
+private fun calculateResultingRippleColor(
+    contentColor: Color,
+    rippleOpacity: Float
+) = contentColor.copy(alpha = rippleOpacity).compositeOver(RippleBoxBackgroundColor)
+
+private val RippleBoxBackgroundColor = Color.Blue
+
+private const val Tag = "Ripple"
\ No newline at end of file
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt b/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
index 5edee25..cd5d33c 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
@@ -164,7 +164,7 @@
         halfStrokeWidth,
         checkboxSize - halfStrokeWidth,
         checkboxSize - halfStrokeWidth,
-        Radius.circular(radius)
+        Radius(radius)
     )
 
     // Determine whether or not we need to offset the inset by a pixel
@@ -188,7 +188,7 @@
                 color,
                 Offset(outer.left, outer.top),
                 Size(outer.width, outer.height),
-                radius,
+                radius = Radius(radius),
                 style = stroke
             )
         }
@@ -208,8 +208,7 @@
             color,
             topLeft = Offset(outer.left, outer.top),
             size = Size(outer.width, outer.height),
-            radiusX = radius,
-            radiusY = radius,
+            radius = Radius(radius),
             style = stroke
         )
     }
@@ -336,4 +335,4 @@
 private val RadiusSize = 2.dp
 
 private val UncheckedBoxOpacity = 0.6f
-private val CheckStrokeDefaultColor = Color.White
\ No newline at end of file
+private val CheckStrokeDefaultColor = Color.White
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Drawer.kt b/ui/ui-material/src/main/java/androidx/ui/material/Drawer.kt
index 89f862a..b7e405d 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Drawer.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Drawer.kt
@@ -16,14 +16,13 @@
 
 package androidx.ui.material
 
-import androidx.animation.AnimatedFloat
 import androidx.animation.PhysicsBuilder
 import androidx.compose.Composable
+import androidx.compose.State
+import androidx.compose.state
 import androidx.ui.core.DensityAmbient
-import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
 import androidx.ui.core.WithConstraints
-import androidx.ui.core.clipToBounds
 import androidx.ui.core.hasBoundedHeight
 import androidx.ui.core.hasBoundedWidth
 import androidx.ui.foundation.Box
@@ -34,14 +33,12 @@
 import androidx.ui.layout.DpConstraints
 import androidx.ui.layout.Stack
 import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.offsetPx
+import androidx.ui.layout.padding
 import androidx.ui.layout.preferredSizeIn
-import androidx.ui.material.internal.StateDraggable
+import androidx.ui.material.internal.stateDraggable
 import androidx.ui.unit.Dp
-import androidx.ui.unit.IntPx
 import androidx.ui.unit.dp
-import androidx.ui.unit.min
-import androidx.ui.unit.px
-import androidx.ui.unit.round
 import androidx.ui.util.lerp
 
 /**
@@ -92,37 +89,39 @@
     drawerContent: @Composable () -> Unit,
     bodyContent: @Composable () -> Unit
 ) {
-    Box(Modifier.fillMaxSize()) {
-        WithConstraints {
-            // TODO : think about Infinite max bounds case
-            if (!constraints.hasBoundedWidth) {
-                throw IllegalStateException("Drawer shouldn't have infinite width")
-            }
-            val dpConstraints = with(DensityAmbient.current) {
-                DpConstraints(constraints)
-            }
-            val minValue = -constraints.maxWidth.value.toFloat()
-            val maxValue = 0f
+    WithConstraints(Modifier.fillMaxSize()) {
+        // TODO : think about Infinite max bounds case
+        if (!constraints.hasBoundedWidth) {
+            throw IllegalStateException("Drawer shouldn't have infinite width")
+        }
+        val dpConstraints = with(DensityAmbient.current) {
+            DpConstraints(constraints)
+        }
+        val minValue = -constraints.maxWidth.value.toFloat()
+        val maxValue = 0f
 
-            val anchors = listOf(minValue to DrawerState.Closed, maxValue to DrawerState.Opened)
-            StateDraggable(
-                state = drawerState,
-                onStateChange = onStateChange,
-                anchorsToState = anchors,
-                animationBuilder = AnimationBuilder,
-                dragDirection = DragDirection.Horizontal,
-                minValue = minValue,
-                maxValue = maxValue,
-                enabled = gesturesEnabled
-            ) { model ->
-                Stack {
-                    bodyContent()
-                    Scrim(drawerState, onStateChange, fraction = {
-                        calculateFraction(minValue, maxValue, model.value)
-                    })
-                    DrawerContent(model, dpConstraints, drawerShape, drawerElevation, drawerContent)
-                }
+        val anchors = listOf(minValue to DrawerState.Closed, maxValue to DrawerState.Opened)
+        val drawerPosition = state { maxValue }
+        Stack(Modifier.stateDraggable(
+            state = drawerState,
+            onStateChange = onStateChange,
+            anchorsToState = anchors,
+            animationBuilder = AnimationBuilder,
+            dragDirection = DragDirection.Horizontal,
+            minValue = minValue,
+            maxValue = maxValue,
+            enabled = gesturesEnabled,
+            onNewValue = { drawerPosition.value = it }
+        )) {
+            Stack {
+                bodyContent()
             }
+            Scrim(drawerState, onStateChange, fraction = {
+                calculateFraction(minValue, maxValue, drawerPosition.value)
+            })
+            DrawerContent(
+                drawerPosition, dpConstraints, drawerShape, drawerElevation, drawerContent
+            )
         }
     }
 }
@@ -163,36 +162,37 @@
     drawerContent: @Composable () -> Unit,
     bodyContent: @Composable () -> Unit
 ) {
-    Box(Modifier.fillMaxSize()) {
-        WithConstraints {
-            // TODO : think about Infinite max bounds case
-            if (!constraints.hasBoundedHeight) {
-                throw IllegalStateException("Drawer shouldn't have infinite height")
-            }
-            val dpConstraints = with(DensityAmbient.current) {
-                DpConstraints(constraints)
-            }
-            val minValue = 0f
-            val maxValue = constraints.maxHeight.value.toFloat()
+    WithConstraints(Modifier.fillMaxSize()) {
+        // TODO : think about Infinite max bounds case
+        if (!constraints.hasBoundedHeight) {
+            throw IllegalStateException("Drawer shouldn't have infinite height")
+        }
+        val dpConstraints = with(DensityAmbient.current) {
+            DpConstraints(constraints)
+        }
+        val minValue = 0f
+        val maxValue = constraints.maxHeight.value.toFloat()
 
-            // TODO: add proper landscape support
-            val isLandscape = constraints.maxWidth > constraints.maxHeight
-            val openedValue = if (isLandscape) minValue else lerp(
-                minValue,
-                maxValue,
-                BottomDrawerOpenFraction
-            )
-            val anchors =
-                if (isLandscape) {
-                    listOf(maxValue to DrawerState.Closed, minValue to DrawerState.Opened)
-                } else {
-                    listOf(
-                        maxValue to DrawerState.Closed,
-                        openedValue to DrawerState.Opened,
-                        minValue to DrawerState.Opened
-                    )
-                }
-            StateDraggable(
+        // TODO: add proper landscape support
+        val isLandscape = constraints.maxWidth > constraints.maxHeight
+        val openedValue = if (isLandscape) minValue else lerp(
+            minValue,
+            maxValue,
+            BottomDrawerOpenFraction
+        )
+        val anchors =
+            if (isLandscape) {
+                listOf(maxValue to DrawerState.Closed, minValue to DrawerState.Opened)
+            } else {
+                listOf(
+                    maxValue to DrawerState.Closed,
+                    openedValue to DrawerState.Opened,
+                    minValue to DrawerState.Opened
+                )
+            }
+        val drawerPosition = state { maxValue }
+        Stack(
+            Modifier.stateDraggable(
                 state = drawerState,
                 onStateChange = onStateChange,
                 anchorsToState = anchors,
@@ -200,19 +200,20 @@
                 dragDirection = DragDirection.Vertical,
                 minValue = minValue,
                 maxValue = maxValue,
-                enabled = gesturesEnabled
-            ) { model ->
-                Stack {
-                    bodyContent()
-                    Scrim(drawerState, onStateChange, fraction = {
-                        // as we scroll "from height to 0" , need to reverse fraction
-                        1 - calculateFraction(openedValue, maxValue, model.value)
-                    })
-                    BottomDrawerContent(
-                        model, dpConstraints, drawerShape, drawerElevation, drawerContent
-                    )
-                }
+                enabled = gesturesEnabled,
+                onNewValue = { drawerPosition.value = it }
+            )
+        ) {
+            Stack {
+                bodyContent()
             }
+            Scrim(drawerState, onStateChange, fraction = {
+                // as we scroll "from height to 0" , need to reverse fraction
+                1 - calculateFraction(openedValue, maxValue, drawerPosition.value)
+            })
+            BottomDrawerContent(
+                drawerPosition, dpConstraints, drawerShape, drawerElevation, drawerContent
+            )
         }
     }
 }
@@ -230,52 +231,41 @@
 
 @Composable
 private fun DrawerContent(
-    xOffset: AnimatedFloat,
+    xOffset: State<Float>,
     constraints: DpConstraints,
     shape: Shape,
     elevation: Dp,
     content: @Composable () -> Unit
 ) {
-    WithOffset(xOffset = xOffset) {
-        Box(
-            Modifier.preferredSizeIn(
-                constraints.minWidth,
-                constraints.minHeight,
-                constraints.maxWidth,
-                constraints.maxHeight
-            ),
-            paddingEnd = VerticalDrawerPadding
-        ) {
-            // remove Container when we will support multiply children
-            Surface(shape = shape, elevation = elevation) {
-                Box(Modifier.fillMaxSize(), children = content)
-            }
-        }
+    Surface(
+        modifier =
+        Modifier
+            .preferredSizeIn(constraints)
+            .offsetPx(x = xOffset)
+            .padding(end = VerticalDrawerPadding),
+        shape = shape,
+        elevation = elevation
+    ) {
+        Box(Modifier.fillMaxSize(), children = content)
     }
 }
 
 @Composable
 private fun BottomDrawerContent(
-    yOffset: AnimatedFloat,
+    yOffset: State<Float>,
     constraints: DpConstraints,
     shape: Shape,
     elevation: Dp,
     content: @Composable () -> Unit
 ) {
-    WithOffset(yOffset = yOffset) {
-        Box(
-            Modifier.preferredSizeIn(
-                constraints.minWidth,
-                constraints.minHeight,
-                constraints.maxWidth,
-                constraints.maxHeight
-            )
-        ) {
-            // remove Container when we will support multiply children
-            Surface(shape = shape, elevation = elevation) {
-                Box(Modifier.fillMaxSize(), children = content)
-            }
-        }
+    Surface(
+        modifier = Modifier
+            .preferredSizeIn(constraints)
+            .offsetPx(y = yOffset),
+        shape = shape,
+        elevation = elevation
+    ) {
+        Box(Modifier.fillMaxSize(), children = content)
     }
 }
 
@@ -288,7 +278,6 @@
     onStateChange: (DrawerState) -> Unit,
     fraction: () -> Float
 ) {
-    // TODO: use enabled = false here when it will be available
     val enabled = state == DrawerState.Opened
     val color = MaterialTheme.colors.onSurface
     Canvas(
@@ -300,38 +289,6 @@
     }
 }
 
-// TODO: consider make pretty and move to public
-@Composable
-private fun WithOffset(
-    xOffset: AnimatedFloat? = null,
-    yOffset: AnimatedFloat? = null,
-    child: @Composable () -> Unit
-) {
-    Layout(children = {
-        Box(Modifier.clipToBounds(), children = child)
-    }) { measurables, constraints, _ ->
-        if (measurables.size > 1) {
-            throw IllegalStateException("Only one child is allowed")
-        }
-        val childMeasurable = measurables.firstOrNull()
-        val placeable = childMeasurable?.measure(constraints)
-        val width: IntPx
-        val height: IntPx
-        if (placeable == null) {
-            width = constraints.minWidth
-            height = constraints.minHeight
-        } else {
-            width = min(placeable.width, constraints.maxWidth)
-            height = min(placeable.height, constraints.maxHeight)
-        }
-        layout(width, height) {
-            val offX = xOffset?.value?.px ?: 0.px
-            val offY = yOffset?.value?.px ?: 0.px
-            placeable?.place(offX.round(), offY.round())
-        }
-    }
-}
-
 private const val ScrimDefaultOpacity = 0.32f
 private val VerticalDrawerPadding = 56.dp
 
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ListItem.kt b/ui/ui-material/src/main/java/androidx/ui/material/ListItem.kt
index 63966c7..a84e856 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ListItem.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ListItem.kt
@@ -175,7 +175,8 @@
 
     if (onClick != null) {
         val indication = RippleIndication(
-            color = MaterialTheme.colors.onSurface.copy(alpha = RippleOpacity)
+            // TODO: should this be defined here? Should we just use the default here instead?
+            color = MaterialTheme.colors.onSurface
         )
         Box(Modifier
             .semantics(mergeAllDescendants = true)
@@ -483,6 +484,3 @@
         }
     }
 }
-
-// Material spec values.
-private const val RippleOpacity = 0.16f
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt b/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
index 24e3fe8..f0fb32e 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
@@ -240,8 +240,8 @@
     radioStroke: Stroke
 ) {
     // TODO(malkov): currently Radio gravity is always CENTER but we need to be flexible
-    val centerW = center.dx
-    val centerH = center.dy
+    val centerW = center.x
+    val centerH = center.y
 
     val center = Offset(centerW, centerH)
     if (gapWidth == 0.0f) {
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt b/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
index a502104..d3cde72 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
@@ -25,7 +25,6 @@
 import androidx.annotation.IntRange
 import androidx.compose.Composable
 import androidx.compose.remember
-import androidx.compose.state
 import androidx.ui.animation.asDisposableClock
 import androidx.ui.core.Alignment
 import androidx.ui.core.AnimationClockAmbient
@@ -35,12 +34,16 @@
 import androidx.ui.core.gesture.pressIndicatorGestureFilter
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.Canvas
+import androidx.ui.foundation.Interaction
+import androidx.ui.foundation.InteractionState
 import androidx.ui.foundation.animation.FlingConfig
 import androidx.ui.foundation.animation.fling
 import androidx.ui.foundation.gestures.DragDirection
 import androidx.ui.foundation.gestures.draggable
+import androidx.ui.foundation.indication
 import androidx.ui.foundation.shape.corner.CircleShape
 import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.PointMode
 import androidx.ui.graphics.StrokeCap
@@ -52,11 +55,10 @@
 import androidx.ui.layout.preferredHeightIn
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.preferredWidthIn
-import androidx.ui.material.ripple.ripple
+import androidx.ui.material.ripple.RippleIndication
 import androidx.ui.semantics.Semantics
 import androidx.ui.semantics.accessibilityValue
 import androidx.ui.unit.dp
-import androidx.ui.unit.px
 import androidx.ui.util.lerp
 import kotlin.math.abs
 
@@ -124,36 +126,43 @@
                         onValueChangeEnd()
                     }
                 }
-                val pressed = state { false }
+
+                val interactionState = remember { InteractionState() }
+
                 val press = Modifier.pressIndicatorGestureFilter(
                     onStart = { pos ->
                         position.holder.snapTo(pos.x)
-                        pressed.value = true
+                        interactionState.addInteraction(Interaction.Pressed, pos)
                     },
                     onStop = {
-                        pressed.value = false
                         gestureEndAction(0f)
-                    })
+                        interactionState.removeInteraction(Interaction.Pressed)
+                    },
+                    onCancel = {
+                        interactionState.removeInteraction(Interaction.Pressed)
+                    }
+                )
 
                 val drag = Modifier.draggable(
                     dragDirection = DragDirection.Horizontal,
+                    interactionState = interactionState,
                     onDragDeltaConsumptionRequested = { delta ->
                         position.holder.snapTo(position.holder.value + delta)
                         // consume all so slider won't participate in nested scrolling
                         delta
                     },
-                    onDragStarted = { pressed.value = true },
-                    onDragStopped = { velocity ->
-                        pressed.value = false
-                        gestureEndAction(velocity)
-                    },
+                    onDragStopped = gestureEndAction,
                     startDragImmediately = position.holder.isRunning
                 )
                 val coerced = value.coerceIn(position.startValue, position.endValue)
                 val fraction = calcFraction(position.startValue, position.endValue, coerced)
                 Semantics(container = true, properties = { accessibilityValue = "$coerced" }) {
                     SliderImpl(
-                        fraction, position.tickFractions, color, maxPx, pressed.value,
+                        fraction,
+                        position.tickFractions,
+                        color,
+                        maxPx,
+                        interactionState,
                         modifier = press.plus(drag)
                     )
                 }
@@ -168,11 +177,11 @@
     tickFractions: List<Float>,
     color: Color,
     width: Float,
-    pressed: Boolean,
+    interactionState: InteractionState,
     modifier: Modifier
 ) {
     val widthDp = with(DensityAmbient.current) {
-        width.px.toDp()
+        width.toDp()
     }
     Stack(modifier + DefaultSliderConstraints) {
         val thumbSize = ThumbRadius * 2
@@ -188,11 +197,24 @@
         val trackStroke = Stroke(trackStrokeWidth, cap = StrokeCap.round)
         Track(center.fillMaxSize(), color, positionFraction, tickFractions, thumbPx, trackStroke)
         Box(center.padding(start = offset)) {
+            val elevation = if (
+                Interaction.Pressed in interactionState || Interaction.Dragged in interactionState
+            ) {
+                ThumbPressedElevation
+            } else {
+                ThumbDefaultElevation
+            }
             Surface(
                 shape = CircleShape,
                 color = color,
-                elevation = if (pressed) 6.dp else 1.dp,
-                modifier = Modifier.ripple(bounded = false)
+                elevation = elevation,
+                modifier = Modifier.indication(
+                    interactionState = interactionState,
+                    indication = RippleIndication(
+                        radius = ThumbRippleRadius,
+                        bounded = false
+                    )
+                )
             ) {
                 Spacer(Modifier.preferredSize(thumbSize, thumbSize))
             }
@@ -212,8 +234,8 @@
     val activeTickColor = MaterialTheme.colors.onPrimary.copy(alpha = TickColorAlpha)
     val inactiveTickColor = color.copy(alpha = TickColorAlpha)
     Canvas(modifier) {
-        val sliderStart = Offset(thumbPx, center.dy)
-        val sliderMax = Offset(size.width - thumbPx, center.dy)
+        val sliderStart = Offset(thumbPx, center.y)
+        val sliderMax = Offset(size.width - thumbPx, center.y)
         drawLine(
             color.copy(alpha = InactiveTrackColorAlpha),
             sliderStart,
@@ -221,15 +243,15 @@
             trackStroke
         )
         val sliderValue = Offset(
-            sliderStart.dx + (sliderMax.dx - sliderStart.dx) * positionFraction,
-            center.dy
+            sliderStart.x + (sliderMax.x - sliderStart.x) * positionFraction,
+            center.y
         )
 
         drawLine(color, sliderStart, sliderValue, trackStroke)
         tickFractions.groupBy { it > positionFraction }.forEach { (afterFraction, list) ->
             drawPoints(
                 list.map {
-                    Offset(Offset.lerp(sliderStart, sliderMax, it).dx, center.dy)
+                    Offset(lerp(sliderStart, sliderMax, it).x, center.y)
                 },
                 PointMode.points,
                 if (afterFraction) inactiveTickColor else activeTickColor,
@@ -355,6 +377,9 @@
 }
 
 private val ThumbRadius = 10.dp
+private val ThumbRippleRadius = 24.dp
+private val ThumbDefaultElevation = 1.dp
+private val ThumbPressedElevation = 6.dp
 private val TrackHeight = 4.dp
 private val SliderHeight = 48.dp
 private val SliderMinWidth = 144.dp // TODO: clarify min width
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt b/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
index c31b3d9..c6425e1 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
@@ -16,9 +16,10 @@
 
 package androidx.ui.material
 
-import androidx.animation.AnimatedFloat
 import androidx.animation.TweenBuilder
 import androidx.compose.Composable
+import androidx.compose.State
+import androidx.compose.state
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
 import androidx.ui.core.semantics.semantics
@@ -33,7 +34,7 @@
 import androidx.ui.graphics.drawscope.Stroke
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredSize
-import androidx.ui.material.internal.StateDraggable
+import androidx.ui.material.internal.stateDraggable
 import androidx.ui.material.ripple.RippleIndication
 import androidx.ui.unit.dp
 
@@ -57,43 +58,34 @@
     enabled: Boolean = true,
     color: Color = MaterialTheme.colors.secondaryVariant
 ) {
-    Box(
-        modifier.semantics(mergeAllDescendants = true).toggleable(
-            value = checked,
-            onValueChange = onCheckedChange,
-            enabled = enabled,
-            indication = RippleIndication(bounded = false)
-        )
-    ) {
-        SwitchImpl(
-            checked, onCheckedChange, color, Modifier.padding(DefaultSwitchPadding)
-        )
-    }
-}
-
-@Composable
-private fun SwitchImpl(
-    checked: Boolean,
-    onCheckedChange: ((Boolean) -> Unit)?,
-    color: Color,
-    modifier: Modifier
-) {
     val minBound = 0f
     val maxBound = with(DensityAmbient.current) { ThumbPathLength.toPx() }
-    StateDraggable(
-        state = checked,
-        onStateChange = onCheckedChange ?: {},
-        anchorsToState = listOf(minBound to false, maxBound to true),
-        animationBuilder = AnimationBuilder,
-        dragDirection = DragDirection.Horizontal,
-        minValue = minBound,
-        maxValue = maxBound
-    ) { model ->
+    val thumbPosition = state { if (checked) maxBound else minBound }
+    Box(
+        modifier
+            .semantics(mergeAllDescendants = true)
+            .toggleable(
+                value = checked,
+                onValueChange = onCheckedChange,
+                enabled = enabled,
+                indication = RippleIndication(bounded = false)
+            )
+            .stateDraggable(
+                state = checked,
+                onStateChange = onCheckedChange,
+                anchorsToState = listOf(minBound to false, maxBound to true),
+                animationBuilder = AnimationBuilder,
+                dragDirection = DragDirection.Horizontal,
+                minValue = minBound,
+                maxValue = maxBound,
+                onNewValue = { thumbPosition.value = it }
+            )
+            .padding(DefaultSwitchPadding)
+    ) {
         DrawSwitch(
             checked = checked,
             checkedThumbColor = color,
-            thumbValue = model,
-            modifier = modifier
+            thumbValue = thumbPosition
         )
     }
 }
@@ -102,8 +94,7 @@
 private fun DrawSwitch(
     checked: Boolean,
     checkedThumbColor: Color,
-    thumbValue: AnimatedFloat,
-    modifier: Modifier
+    thumbValue: State<Float>
 ) {
     val thumbColor = if (checked) checkedThumbColor else MaterialTheme.colors.surface
     val trackColor = if (checked) {
@@ -116,7 +107,7 @@
     with(DensityAmbient.current) {
         trackStroke = Stroke(width = TrackStrokeWidth.toPx(), cap = StrokeCap.round)
     }
-    Canvas(modifier.preferredSize(SwitchWidth, SwitchHeight)) {
+    Canvas(Modifier.preferredSize(SwitchWidth, SwitchHeight)) {
         drawTrack(trackColor, TrackWidth.toPx(), trackStroke)
         drawThumb(thumbValue.value, ThumbDiameter.toPx(), thumbColor)
     }
@@ -126,8 +117,8 @@
     val strokeRadius = stroke.width / 2
     drawLine(
         trackColor,
-        Offset(strokeRadius, center.dy),
-        Offset(trackWidth - strokeRadius, center.dy),
+        Offset(strokeRadius, center.y),
+        Offset(trackWidth - strokeRadius, center.y),
         stroke
     )
 }
@@ -135,7 +126,7 @@
 private fun DrawScope.drawThumb(position: Float, thumbDiameter: Float, thumbColor: Color) {
     val thumbRadius = thumbDiameter / 2
     val x = position + thumbRadius
-    drawCircle(thumbColor, thumbRadius, Offset(x, center.dy))
+    drawCircle(thumbColor, thumbRadius, Offset(x, center.y))
 }
 
 private const val CheckedTrackOpacity = 0.54f
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
index 0b7393d..066358b 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
@@ -65,7 +65,6 @@
 import androidx.ui.unit.dp
 import androidx.ui.unit.max
 import androidx.ui.unit.sp
-import androidx.ui.unit.toPx
 import androidx.ui.util.fastFirstOrNull
 import androidx.ui.util.fastForEach
 import androidx.ui.util.fastForEachIndexed
@@ -360,7 +359,7 @@
         // How much space we have to scroll. If the visible width is <= to the total width, then
         // we have no space to scroll as everything is always visible.
         val availableSpace = (totalTabRowWidth - visibleWidth).coerceAtLeast(IntPx.Zero)
-        return centeredTabOffset.coerceIn(IntPx.Zero, availableSpace).toPx().value
+        return centeredTabOffset.coerceIn(IntPx.Zero, availableSpace).value.toFloat()
     }
 }
 
@@ -432,13 +431,13 @@
                 // When this is supported by transitionDefinition, we should fix this to just set a
                 // default or similar.
                 state(selectedIndex) {
-                    this[IndicatorOffset] = tabPositions[selectedIndex].left.toPx().value
+                    this[IndicatorOffset] = tabPositions[selectedIndex].left.value.toFloat()
                 }
 
                 tabPositions.forEachIndexed { index, position ->
                     if (index != selectedIndex) {
                         state(index) {
-                            this[IndicatorOffset] = position.left.toPx().value
+                            this[IndicatorOffset] = position.left.value.toFloat()
                         }
                     }
                 }
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
index 70850b8..e37b6c1 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
@@ -20,9 +20,13 @@
 import androidx.animation.TransitionSpec
 import androidx.animation.TweenBuilder
 import androidx.animation.transitionDefinition
+import androidx.annotation.VisibleForTesting
 import androidx.compose.Composable
 import androidx.compose.Providers
+import androidx.compose.Stable
+import androidx.compose.StructurallyEqual
 import androidx.compose.getValue
+import androidx.compose.mutableStateOf
 import androidx.compose.remember
 import androidx.compose.setValue
 import androidx.compose.state
@@ -40,6 +44,7 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.Placeable
 import androidx.ui.core.Ref
+import androidx.ui.core.clipToBounds
 import androidx.ui.core.drawBehind
 import androidx.ui.core.offset
 import androidx.ui.core.tag
@@ -54,6 +59,9 @@
 import androidx.ui.foundation.TextFieldValue
 import androidx.ui.foundation.clickable
 import androidx.ui.foundation.currentTextStyle
+import androidx.ui.foundation.gestures.DragDirection
+import androidx.ui.foundation.gestures.ScrollableState
+import androidx.ui.foundation.gestures.scrollable
 import androidx.ui.foundation.shape.corner.ZeroCornerSize
 import androidx.ui.geometry.Offset
 import androidx.ui.graphics.Color
@@ -65,8 +73,8 @@
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredSizeIn
 import androidx.ui.material.ripple.RippleIndication
+import androidx.ui.savedinstancestate.rememberSavedInstanceState
 import androidx.ui.semantics.Semantics
-import androidx.ui.text.FirstBaseline
 import androidx.ui.text.LastBaseline
 import androidx.ui.text.SoftwareKeyboardController
 import androidx.ui.text.TextRange
@@ -78,6 +86,8 @@
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import androidx.ui.unit.max
+import androidx.ui.unit.min
+import kotlin.math.roundToInt
 
 /**
  * Material Design implementation of the
@@ -384,24 +394,29 @@
             typography = MaterialTheme.typography.subtitle1,
             emphasis = EmphasisAmbient.current.high
         ) {
-            TextField(
-                value = value,
-                modifier = tagModifier + focusModifier,
-                textStyle = textStyle,
-                onValueChange = onValueChange,
-                onFocusChange = onFocusChange,
-                cursorColor = if (isErrorValue) errorColor else activeColor,
-                visualTransformation = visualTransformation,
-                keyboardType = keyboardType,
-                imeAction = imeAction,
-                onImeActionPerformed = {
-                    onImeActionPerformed(it, keyboardController.value)
-                },
-                onTextInputStarted = {
-                    keyboardController.value = it
-                    onTextInputStarted(it)
-                }
-            )
+            TextFieldScroller(
+                scrollerPosition = rememberSavedInstanceState { TextFieldScrollerPosition() },
+                modifier = tagModifier
+            ) {
+                TextField(
+                    value = value,
+                    modifier = tagModifier + focusModifier,
+                    textStyle = textStyle,
+                    onValueChange = onValueChange,
+                    onFocusChange = onFocusChange,
+                    cursorColor = if (isErrorValue) errorColor else activeColor,
+                    visualTransformation = visualTransformation,
+                    keyboardType = keyboardType,
+                    imeAction = imeAction,
+                    onImeActionPerformed = {
+                        onImeActionPerformed(it, keyboardController.value)
+                    },
+                    onTextInputStarted = {
+                        keyboardController.value = it
+                        onTextInputStarted(it)
+                    }
+                )
+            }
         }
     }
 
@@ -483,6 +498,59 @@
 }
 
 /**
+ * Similar to [androidx.ui.foundation.VerticalScroller] but does not lose the minWidth constraints.
+ */
+@VisibleForTesting
+@Composable
+internal fun TextFieldScroller(
+    scrollerPosition: TextFieldScrollerPosition,
+    modifier: Modifier = Modifier,
+    textField: @Composable () -> Unit
+) {
+    Layout(
+        modifier = modifier
+            .clipToBounds()
+            .scrollable(
+                scrollableState = ScrollableState { delta ->
+                    val newPosition = scrollerPosition.current + delta
+                    val consumedDelta = when {
+                        newPosition > scrollerPosition.maximum ->
+                            scrollerPosition.maximum - scrollerPosition.current // too much down
+                        newPosition < 0f -> -scrollerPosition.current // scrolled too much up
+                        else -> delta
+                    }
+                    scrollerPosition.current += consumedDelta
+                    consumedDelta
+                },
+                dragDirection = DragDirection.Vertical,
+                enabled = scrollerPosition.maximum != 0f
+            ),
+        children = textField,
+        measureBlock = { measurables, constraints, _ ->
+            val childConstraints = constraints.copy(maxHeight = IntPx.Infinity)
+            val placeable = measurables.first().measure(childConstraints)
+            val height = min(placeable.height, constraints.maxHeight)
+            val diff = placeable.height.value.toFloat() - height.value.toFloat()
+            layout(placeable.width, height) {
+                // update current and maximum positions to correctly calculate delta in scrollable
+                scrollerPosition.maximum = diff
+                if (scrollerPosition.current > diff) scrollerPosition.current = diff
+
+                val yOffset = scrollerPosition.current - diff
+                placeable.place(0.ipx, yOffset.roundToInt().ipx)
+            }
+        }
+    )
+}
+
+@VisibleForTesting
+@Stable
+internal class TextFieldScrollerPosition {
+    var current by mutableStateOf(0f, StructurallyEqual)
+    var maximum by mutableStateOf(Float.POSITIVE_INFINITY, StructurallyEqual)
+}
+
+/**
  * Set alpha if the color is not translucent
  */
 private fun Color.applyAlpha(alpha: Float): Color {
@@ -547,17 +615,13 @@
         val textfieldPlaceable = measurables
             .first { it.tag == TextFieldTag }
             .measure(textFieldConstraints)
-        val textfieldFirstBaseline = requireNotNull(textfieldPlaceable[FirstBaseline]) {
-            "No text first baseline."
-        }
         val textfieldLastBaseline = requireNotNull(textfieldPlaceable[LastBaseline]) {
             "No text last baseline."
         }
-        val textfieldPositionY = effectiveLabelBaseline + baseLineOffset - textfieldFirstBaseline
 
         val width = max(textfieldPlaceable.width, constraints.minWidth)
         val height = max(
-            textfieldPositionY + textfieldLastBaseline + LastBaselineOffset.toIntPx(),
+            effectiveLabelBaseline + textfieldPlaceable.height + LastBaselineOffset.toIntPx(),
             constraints.minHeight
         )
 
@@ -565,6 +629,9 @@
             // Text field and label are placed with respect to the baseline offsets.
             // But if label is empty, then the text field should be centered vertically.
             if (labelPlaceable.width != IntPx.Zero) {
+                // only respects the offset from the last baseline to the bottom of the text field
+                val textfieldPositionY = height - LastBaselineOffset.toIntPx() -
+                        min(textfieldLastBaseline, textfieldPlaceable.height)
                 placeLabelAndTextfield(
                     width,
                     height,
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
index 6758f33..11b3813 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
@@ -18,14 +18,16 @@
 
 import androidx.animation.AnimatedFloat
 import androidx.animation.AnimationBuilder
+import androidx.animation.AnimationClockObservable
 import androidx.animation.AnimationEndReason
-import androidx.compose.Composable
+import androidx.animation.Spring
 import androidx.compose.onCommit
 import androidx.compose.remember
 import androidx.compose.state
-import androidx.ui.animation.animatedFloat
+import androidx.ui.core.AnimationClockAmbient
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
+import androidx.ui.core.composed
+import androidx.ui.foundation.InteractionState
 import androidx.ui.foundation.animation.AnchorsFlingConfig
 import androidx.ui.foundation.animation.fling
 import androidx.ui.foundation.gestures.DragDirection
@@ -33,21 +35,20 @@
 import androidx.ui.util.fastFirstOrNull
 
 /**
- * Higher-level component that allows dragging around anchored positions binded to different states
+ * Enable automatic drag and animation between predefined states.
  *
- * Example might be a Switch which you can drag between two states (true or false).
+ * This can be used for example in a Switch to enable dragging between two states (true and
+ * false). Additionally, it will animate correctly when the value of the state parameter is changed.
  *
- * Additional features compared to regular [draggable] modifier:
- * 1. The AnimatedFloat hosted inside and its value will be in sync with call site state
+ * Additional features compared to [draggable]:
+ * 1. [onNewValue] provides the developer with the new value every time drag or animation (caused
+ * by fling or [state] change) occurs. The developer needs to hold this state on their own
  * 2. When the anchor is reached, [onStateChange] will be called with state mapped to this anchor
  * 3. When the anchor is reached and [onStateChange] with corresponding state is called, but
  * call site didn't update state to the reached one for some reason,
  * this component performs rollback to the previous (correct) state.
  * 4. When new [state] is provided, component will be animated to state's anchor
  *
- * children of this composable will receive [AnimatedFloat] class from which
- * they can read current value when they need or manually animate.
- *
  * @param T type with which state is represented
  * @param state current state to represent Float value with
  * @param onStateChange callback to update call site's state
@@ -55,13 +56,13 @@
  * @param animationBuilder animation which will be used for animations
  * @param dragDirection direction in which drag should be happening.
  * Either [DragDirection.Vertical] or [DragDirection.Horizontal]
+ * @param enabled whether or not this Draggable is enabled and should consume events
  * @param minValue lower bound for draggable value in this component
  * @param maxValue upper bound for draggable value in this component
- * @param enabled whether or not this Draggable is enabled and should consume events
+ * @param onNewValue callback to update state that the developer owns when animation or drag occurs
  */
 // TODO(malkov/tianliu) (figure our how to make it better and make public)
-@Composable
-internal fun <T> StateDraggable(
+internal fun <T> Modifier.stateDraggable(
     state: T,
     onStateChange: (T) -> Unit,
     anchorsToState: List<Pair<Float, T>>,
@@ -70,8 +71,9 @@
     enabled: Boolean = true,
     minValue: Float = Float.MIN_VALUE,
     maxValue: Float = Float.MAX_VALUE,
-    content: @Composable (AnimatedFloat) -> Unit
-) {
+    interactionState: InteractionState? = null,
+    onNewValue: (Float) -> Unit
+) = composed {
     val forceAnimationCheck = state { true }
 
     val anchors = remember(anchorsToState) { anchorsToState.map { it.first } }
@@ -86,7 +88,12 @@
                 }
             }
         })
-    val position = animatedFloat(currentValue)
+    val clocks = AnimationClockAmbient.current
+    val position = remember(clocks) {
+        onNewValue(currentValue)
+        NotificationBasedAnimatedFloat(currentValue, clocks, onNewValue)
+    }
+    position.onNewValue = onNewValue
     position.setBounds(minValue, maxValue)
 
     // This state is to force this component to be recomposed and trigger onCommit below
@@ -94,7 +101,7 @@
     onCommit(currentValue, forceAnimationCheck.value) {
         position.animateTo(currentValue, animationBuilder)
     }
-    val draggable = Modifier.draggable(
+    Modifier.draggable(
         dragDirection = dragDirection,
         onDragDeltaConsumptionRequested = { delta ->
             val old = position.value
@@ -103,12 +110,20 @@
         },
         onDragStopped = { position.fling(flingConfig, it) },
         enabled = enabled,
-        startDragImmediately = position.isRunning
+        startDragImmediately = position.isRunning,
+        interactionState = interactionState
     )
-    // TODO(b/150706555): This layout is temporary and should be removed once Semantics
-    //  is implemented with modifiers.
-    @Suppress("DEPRECATION")
-    PassThroughLayout(draggable) {
-        content(position)
-    }
+}
+
+private class NotificationBasedAnimatedFloat(
+    initial: Float,
+    clock: AnimationClockObservable,
+    internal var onNewValue: (Float) -> Unit
+) : AnimatedFloat(clock, Spring.DefaultDisplacementThreshold) {
+
+    override var value = initial
+        set(value) {
+            onNewValue(value)
+            field = value
+        }
 }
\ No newline at end of file
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/Ripple.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/Ripple.kt
index 7339110..6b15052 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/Ripple.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ripple/Ripple.kt
@@ -40,12 +40,14 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.composed
 import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.foundation.Interaction
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.useOrElse
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
+import androidx.ui.unit.PxSize
 import androidx.ui.unit.center
 import androidx.ui.unit.ipx
 import androidx.ui.unit.toPxSize
@@ -54,10 +56,7 @@
 /**
  * Ripple is a [Modifier] which draws the visual indicator for a pressed state.
  *
- * Ripple responds to a tap by starting a new [RippleEffect] animation.
- * For creating an effect it uses the [RippleTheme.factory].
- *
- * @sample androidx.ui.material.samples.RippleSample
+ * Ripple responds to a tap by starting a new ripple animation.
  *
  * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
  * ripples always animate from the target layout center, bounded ripples animate from the touch
@@ -70,6 +69,10 @@
  * @param clock The animation clock observable that will drive this ripple effect
  * @param enabled The ripple effect will not start if false is provided.
  */
+@Deprecated("Use Modifier.clickable to handle click events and show a ripple, or use " +
+        "Modifier.indication directly with RippleIndication just to show a ripple. If you already" +
+        " have a clickable / toggleable in this modifier chain, you can directly delete this " +
+        "ripple without replacement.")
 fun Modifier.ripple(
     bounded: Boolean = true,
     radius: Dp? = null,
@@ -82,16 +85,18 @@
     val density = DensityAmbient.current
     val rippleModifier = remember { RippleModifier() }
     val theme = RippleThemeAmbient.current
-    rippleModifier.color = (color.useOrElse { theme.defaultColor() }).copy(alpha = theme.opacity())
+    val rippleColor = color.useOrElse { theme.defaultColor() }
+    val rippleAlpha = theme.rippleOpacity().opacityForInteraction(Interaction.Pressed)
+    rippleModifier.color = rippleColor.copy(alpha = rippleAlpha)
 
     val pressIndicator = Modifier.pressIndicatorGestureFilter(
         onStart = { position ->
             if (enabled && transitionsEnabled) {
-                rippleModifier.handleStart(position, theme.factory, density, bounded, radius, clock)
+                rippleModifier.handleStart(position, density, bounded, radius, clock)
             }
         },
-        onStop = { rippleModifier.handleFinish(false) },
-        onCancel = { rippleModifier.handleFinish(true) }
+        onStop = { rippleModifier.handleFinish() },
+        onCancel = { rippleModifier.handleFinish() }
     )
     pressIndicator + rippleModifier
 }
@@ -101,8 +106,8 @@
     var color: Color by mutableStateOf(Color.Transparent, StructurallyEqual)
 
     private var size: IntPxSize = IntPxSize(0.ipx, 0.ipx)
-    private var effects = modelListOf<RippleEffect>()
-    private var currentEffect: RippleEffect? = null
+    private var effects = modelListOf<RippleAnimation>()
+    private var currentEffect: RippleAnimation? = null
 
     override fun MeasureScope.measure(
         measurable: Measurable,
@@ -117,25 +122,27 @@
     }
 
     fun handleStart(
-        touchPosition: PxPosition,
-        factory: RippleEffectFactory,
+        touchPosition: Offset,
         density: Density,
         bounded: Boolean,
         radius: Dp?,
         clock: AnimationClockObservable
     ) {
         val position = if (bounded) touchPosition else size.toPxSize().center()
-        val onAnimationFinished = { effect: RippleEffect ->
+        val onAnimationFinished = { effect: RippleAnimation ->
             effects.remove(effect)
             if (currentEffect == effect) {
                 currentEffect = null
             }
         }
-        val effect = factory.create(
+        val targetRadius = with(density) {
+            radius?.toPx() ?: getRippleEndRadius(bounded, PxSize(size.width, size.height))
+        }
+
+        val effect = RippleAnimation(
             size.toPxSize(),
             position,
-            density,
-            radius,
+            targetRadius,
             bounded,
             clock,
             onAnimationFinished
@@ -145,8 +152,8 @@
         currentEffect = effect
     }
 
-    fun handleFinish(canceled: Boolean) {
-        currentEffect?.finish(canceled)
+    fun handleFinish() {
+        currentEffect?.finish()
         currentEffect = null
     }
 
@@ -164,7 +171,6 @@
     }
 
     override fun onLeave() {
-        effects.fastForEach { it.dispose() }
         effects.clear()
         currentEffect = null
     }
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/DefaultRippleEffect.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleAnimation.kt
similarity index 81%
rename from ui/ui-material/src/main/java/androidx/ui/material/ripple/DefaultRippleEffect.kt
rename to ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleAnimation.kt
index 0318a14..fac6d35 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/DefaultRippleEffect.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleAnimation.kt
@@ -33,47 +33,21 @@
 import androidx.ui.graphics.drawscope.DrawScope
 import androidx.ui.graphics.drawscope.clipRect
 import androidx.ui.unit.Density
-import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.center
 import androidx.ui.unit.dp
-import androidx.ui.unit.getDistance
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.milliseconds
-import androidx.ui.unit.toOffset
 import kotlin.math.max
 
 /**
- * Used to specify this type of [RippleEffect] for [ripple].
- */
-object DefaultRippleEffectFactory : RippleEffectFactory {
-
-    override fun create(
-        size: PxSize,
-        startPosition: PxPosition,
-        density: Density,
-        radius: Dp?,
-        clipped: Boolean,
-        clock: AnimationClockObservable,
-        onAnimationFinished: ((RippleEffect) -> Unit)
-    ): RippleEffect {
-        return DefaultRippleEffect(
-            size,
-            startPosition,
-            density,
-            radius,
-            clipped,
-            clock,
-            onAnimationFinished
-        )
-    }
-}
-
-/**
- * [RippleEffect]s are drawn as part of [ripple] as a visual indicator for a pressed state.
+ * [RippleAnimation]s are drawn as part of [RippleIndication] as a visual indicator for an
+ * [androidx.ui.foundation.Interaction.Pressed] state.
  *
- * Use [ripple] to add an animation for your component.
+ * Use [androidx.ui.foundation.clickable] or [androidx.ui.foundation.indication] to add a
+ * [RippleIndication] to your component, which contains a RippleAnimation for pressed states, and
+ * a state layer for other states.
  *
  * This is a default implementation based on the Material Design specification.
  *
@@ -84,21 +58,19 @@
  *
  * @param size The size of the target layout.
  * @param startPosition The position the animation will start from.
- * @param density The [Density] object to convert the dimensions.
  * @param radius Effects grow up to this size.
  * @param clipped If true the effect should be clipped by the target layout bounds.
  * @param clock The animation clock observable that will drive this ripple effect
  * @param onAnimationFinished Call when the effect animation has been finished.
  */
-private class DefaultRippleEffect(
+internal class RippleAnimation(
     size: PxSize,
-    startPosition: PxPosition,
-    density: Density,
-    radius: Dp? = null,
+    startPosition: Offset,
+    radius: Float,
     private val clipped: Boolean,
     clock: AnimationClockObservable,
-    private val onAnimationFinished: ((RippleEffect) -> Unit)
-) : RippleEffect {
+    private val onAnimationFinished: (RippleAnimation) -> Unit
+) {
 
     private val animation: TransitionAnimation<RippleTransition.State>
     private var transitionState = RippleTransition.State.Initial
@@ -108,9 +80,7 @@
     init {
         val surfaceSize = size
         val startRadius = getRippleStartRadius(surfaceSize)
-        val targetRadius = with(density) {
-            radius?.toPx() ?: getRippleEndRadius(clipped, surfaceSize)
-        }
+        val targetRadius = radius
 
         val center = size.center()
         animation = RippleTransition.definition(
@@ -133,12 +103,12 @@
         animation.toState(RippleTransition.State.Revealed)
     }
 
-    override fun finish(canceled: Boolean) {
+    fun finish() {
         finishRequested = true
         animation.toState(RippleTransition.State.Finished)
     }
 
-    override fun DrawScope.draw(color: Color) {
+    fun DrawScope.draw(color: Color) {
         animationPulse // model read so we will be redrawn with the next animation values
 
         val alpha = if (transitionState == RippleTransition.State.Initial && finishRequested) {
@@ -148,7 +118,7 @@
             animation[RippleTransition.Alpha]
         }
 
-        val centerOffset = animation[RippleTransition.Center].toOffset()
+        val centerOffset = animation[RippleTransition.Center]
         val radius = animation[RippleTransition.Radius]
 
         val modulatedColor = color.copy(alpha = color.alpha * alpha)
@@ -187,8 +157,8 @@
     fun definition(
         startRadius: Float,
         endRadius: Float,
-        startCenter: PxPosition,
-        endCenter: PxPosition
+        startCenter: Offset,
+        endCenter: Offset
     ) = transitionDefinition {
         state(State.Initial) {
             this[Alpha] = 0f
@@ -248,7 +218,7 @@
  */
 internal fun Density.getRippleEndRadius(bounded: Boolean, size: PxSize): Float {
     val radiusCoveringBounds =
-        (PxPosition(size.width, size.height).getDistance() / 2f).value
+        (Offset(size.width, size.height).getDistance() / 2f)
     return if (bounded) {
         radiusCoveringBounds + BoundedRippleExtraRadius.toPx()
     } else {
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffect.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffect.kt
deleted file mode 100644
index 89f30bb..0000000
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffect.kt
+++ /dev/null
@@ -1,47 +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.ui.material.ripple
-
-import androidx.ui.graphics.Color
-import androidx.ui.graphics.drawscope.DrawScope
-
-/**
- * [RippleEffect]s are drawn as part of [ripple] as a visual indicator for a pressed state.
- *
- * Use [ripple] to add an animation for your component.
- */
-interface RippleEffect {
-
-    /**
-     * Override this method to draw the ripple.
-     *
-     * @param color The [Color] for this [RippleEffect].
-     */
-    fun DrawScope.draw(color: Color)
-
-    /**
-     * Called when the user input that triggered this effect was confirmed or canceled.
-     *
-     * Typically causes the ripple to start disappearance animation.
-     */
-    fun finish(canceled: Boolean)
-
-    /**
-     * Free up the resources associated with this ripple.
-     */
-    fun dispose() {}
-}
\ No newline at end of file
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffectFactory.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffectFactory.kt
deleted file mode 100644
index 6c796ac..0000000
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleEffectFactory.kt
+++ /dev/null
@@ -1,54 +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.ui.material.ripple
-
-import androidx.animation.AnimationClockObservable
-import androidx.ui.unit.Density
-import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.PxSize
-
-/**
- * An encapsulation of an [RippleEffect] constructor used by [ripple] and [RippleTheme].
- *
- * Will be used as a theme parameter in [RippleTheme.factory]
- */
-interface RippleEffectFactory {
-
-    /**
-     * The factory method.
-     *
-     * Subclasses should override this method to return a new instance of an [RippleEffect].
-     *
-     * @param size The size of the target layout.
-     * @param startPosition The position the animation will start from.
-     * @param density The [Density] object to convert the dimensions.
-     * @param radius Effects grow up to this size.
-     * @param clipped If true the effect should be clipped by the target layout bounds.
-     * @param clock The animation clock observable that will drive this ripple effect
-     * @param onAnimationFinished Call when the effect animation has been finished.
-     */
-    fun create(
-        size: PxSize,
-        startPosition: PxPosition,
-        density: Density,
-        radius: Dp?,
-        clipped: Boolean,
-        clock: AnimationClockObservable,
-        onAnimationFinished: ((RippleEffect) -> Unit)
-    ): RippleEffect
-}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleIndication.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleIndication.kt
index 9fc5c67..ea273c3 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleIndication.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleIndication.kt
@@ -16,13 +16,18 @@
 
 package androidx.ui.material.ripple
 
+import androidx.animation.AnimationBuilder
 import androidx.animation.AnimationClockObservable
+import androidx.animation.LinearEasing
+import androidx.animation.TweenBuilder
 import androidx.compose.Composable
+import androidx.compose.Stable
 import androidx.compose.State
 import androidx.compose.StructurallyEqual
 import androidx.compose.frames.modelListOf
 import androidx.compose.remember
 import androidx.compose.state
+import androidx.ui.animation.AnimatedFloatModel
 import androidx.ui.animation.asDisposableClock
 import androidx.ui.core.AnimationClockAmbient
 import androidx.ui.core.ContentDrawScope
@@ -31,26 +36,29 @@
 import androidx.ui.foundation.Interaction
 import androidx.ui.foundation.InteractionState
 import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.DrawScope
+import androidx.ui.graphics.drawscope.clipRect
 import androidx.ui.graphics.useOrElse
 import androidx.ui.material.MaterialTheme
 import androidx.ui.unit.Dp
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.center
-import androidx.ui.unit.px
 import androidx.ui.util.fastForEach
 
 /**
  * Material implementation of [IndicationInstance] that expresses indication via ripples. This
- * [IndicationInstance] will be used by default in Modifier.indication() if you have a [MaterialTheme]
- * set in your hierarchy.
+ * [IndicationInstance] will be used by default in Modifier.indication() if you have a
+ * [MaterialTheme] set in your hierarchy.
  *
- * Ripple responds to a tap by starting a new [RippleEffect] animation.
- * For creating an effect it uses the [RippleTheme.factory].
+ * RippleIndication responds to [Interaction.Pressed] by starting a new [RippleAnimation], and
+ * responds to other interactions by showing a fixed state layer.
  *
- * By default this [Indication] with default parameters will be provided by
- * [MaterialTheme]. You can also manually create a [RippleIndication] and provide it to [Modifier
- * .indication] in order to customize its appearance.
+ * By default this [Indication] with default parameters will be provided by [MaterialTheme]
+ * through [androidx.ui.foundation.IndicationAmbient], and hence used in interactions such as
+ * [androidx.ui.foundation.clickable] out of the box. You can also manually create a
+ * [RippleIndication] and provide it to [androidx.ui.foundation.indication] in order to
+ * customize its appearance.
  *
  * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
  * ripples always animate from the target layout center, bounded ripples animate from the touch
@@ -59,7 +67,7 @@
  * based on the target layout size.
  * @param color The Ripple color is usually the same color used by the text or iconography in the
  * component. If [Color.Unset] is provided the color will be calculated by
- * [RippleTheme.defaultColor].
+ * [RippleTheme.defaultColor]. This color will then have [RippleTheme.rippleOpacity] applied
  */
 @Composable
 fun RippleIndication(
@@ -67,39 +75,41 @@
     radius: Dp? = null,
     color: Color = Color.Unset
 ): RippleIndication {
-    val rippleTheme = RippleThemeAmbient.current
-    val resolvedColor =
-        (color.useOrElse { rippleTheme.defaultColor() }).copy(alpha = rippleTheme.opacity())
+    val theme = RippleThemeAmbient.current
+    val clock = AnimationClockAmbient.current.asDisposableClock()
+    val resolvedColor = color.useOrElse { theme.defaultColor() }
     val colorState = state(StructurallyEqual) { resolvedColor }
-    val clocks = AnimationClockAmbient.current.asDisposableClock()
-    val indication = remember(bounded, radius, clocks, rippleTheme) {
-        RippleIndication(bounded, radius, colorState, rippleTheme.factory, clocks)
-    }
     colorState.value = resolvedColor
-    return indication
+    val interactionOpacity = theme.rippleOpacity()
+    return remember(bounded, radius, theme, clock) {
+        RippleIndication(bounded, radius, colorState, interactionOpacity, clock)
+    }
 }
 
 /**
  * Material implementation of [IndicationInstance] that expresses indication via ripples. This
- * [IndicationInstance] will be used by default in Modifier.indication() if you have a [MaterialTheme]
- * set in your hierarchy.
+ * [IndicationInstance] will be used by default in Modifier.indication() if you have a
+ * [MaterialTheme] set in your hierarchy.
  *
- * Ripple responds to a tap by starting a new [RippleEffect] animation.
- * For creating an effect it uses the [RippleTheme.factory].
+ * RippleIndication responds to [Interaction.Pressed] by starting a new [RippleAnimation], and
+ * responds to other interactions by showing a fixed state layer.
  *
- * By default an [Indication] that creates instances of this class will be provided by
- * [MaterialTheme]. You can also manually create a [RippleIndicationInstance] and provide it to [Modifier
- * .indication] in order to customize its appearance.
+ * By default this [Indication] with default parameters will be provided by [MaterialTheme]
+ * through [androidx.ui.foundation.IndicationAmbient], and hence used in interactions such as
+ * [androidx.ui.foundation.clickable] out of the box. You can also manually create a
+ * [RippleIndication] and provide it to [androidx.ui.foundation.indication] in order to
+ * customize its appearance.
  */
+@Stable
 class RippleIndication internal constructor(
     private val bounded: Boolean,
     private val radius: Dp? = null,
     private var color: State<Color>,
-    private val factory: RippleEffectFactory,
+    private val rippleOpacity: RippleOpacity,
     private val clock: AnimationClockObservable
 ) : Indication {
     override fun createInstance(): IndicationInstance {
-        return RippleIndicationInstance(bounded, radius, color, factory, clock)
+        return RippleIndicationInstance(bounded, radius, color, rippleOpacity, clock)
     }
 
     // to force stability on this indication we need equals and hashcode, there's no value in
@@ -113,7 +123,7 @@
         if (bounded != other.bounded) return false
         if (radius != other.radius) return false
         if (color != other.color) return false
-        if (factory != other.factory) return false
+        if (rippleOpacity != other.rippleOpacity) return false
         if (clock != other.clock) return false
 
         return true
@@ -123,7 +133,7 @@
         var result = bounded.hashCode()
         result = 31 * result + (radius?.hashCode() ?: 0)
         result = 31 * result + color.hashCode()
-        result = 31 * result + factory.hashCode()
+        result = 31 * result + rippleOpacity.hashCode()
         result = 31 * result + clock.hashCode()
         return result
     }
@@ -133,58 +143,152 @@
     private val bounded: Boolean,
     private val radius: Dp? = null,
     private var color: State<Color>,
-    private val factory: RippleEffectFactory,
+    private val rippleOpacity: RippleOpacity,
     private val clock: AnimationClockObservable
 ) : IndicationInstance {
 
-    private val effects = modelListOf<RippleEffect>()
-    private var currentPressPosition: PxPosition? = null
-    private var currentEffect: RippleEffect? = null
+    private val stateLayer = StateLayer(clock, bounded, rippleOpacity)
+
+    private val ripples = modelListOf<RippleAnimation>()
+    private var currentPressPosition: Offset? = null
+    private var currentRipple: RippleAnimation? = null
 
     override fun ContentDrawScope.drawIndication(interactionState: InteractionState) {
-        refreshEffectsState(interactionState)
+        val targetRadius =
+            radius?.toPx() ?: getRippleEndRadius(bounded, PxSize(size.width, size.height))
         drawContent()
-        effects.fastForEach {
-            with(it) {
-                draw(color.value)
+        with(stateLayer) {
+            drawStateLayer(interactionState, targetRadius, color.value)
+        }
+        val pressPosition = interactionState.interactionPositionFor(Interaction.Pressed)
+        if (pressPosition != null) {
+            if (currentPressPosition != pressPosition) {
+                addRipple(targetRadius, pressPosition)
             }
+        } else {
+            // TODO: possibly handle cancelling the animation here, need to clarify spec for when
+            // ripples and state layers overlap
+            removeRipple()
         }
+        drawRipples(color.value)
     }
 
-    private fun ContentDrawScope.refreshEffectsState(state: InteractionState) {
-        val pressPosition = state.interactionPositionFor(Interaction.Pressed)
-        if (pressPosition == null) {
-            cleanPressState()
-        } else if (currentPressPosition != pressPosition) {
-            startRippleEffect(pressPosition)
-        }
-    }
-
-    private fun ContentDrawScope.startRippleEffect(pressPosition: PxPosition) {
-        currentEffect?.finish(false)
-        val pxSize = PxSize(size.width.px, size.height.px)
+    private fun ContentDrawScope.addRipple(targetRadius: Float, pressPosition: Offset) {
+        currentRipple?.finish()
+        val pxSize = PxSize(size.width, size.height)
         val position = if (bounded) pressPosition else pxSize.center()
-        val effect =
-            factory.create(pxSize, position, this, radius, bounded, clock) { effect ->
-                effects.remove(effect)
-                if (currentEffect == effect) {
-                    currentEffect = null
-                }
+        val ripple = RippleAnimation(pxSize, position, targetRadius, bounded, clock) { ripple ->
+            ripples.remove(ripple)
+            if (currentRipple == ripple) {
+                currentRipple = null
             }
-        effects.add(effect)
+        }
+        ripples.add(ripple)
         currentPressPosition = pressPosition
-        currentEffect = effect
+        currentRipple = ripple
     }
 
-    private fun cleanPressState() {
-        currentEffect?.finish(false)
-        currentEffect = null
+    private fun removeRipple() {
+        currentRipple?.finish()
+        currentRipple = null
         currentPressPosition = null
     }
 
+    private fun DrawScope.drawRipples(color: Color) {
+        ripples.fastForEach {
+            with(it) {
+                val alpha = rippleOpacity.opacityForInteraction(Interaction.Pressed)
+                if (alpha != 0f) {
+                    draw(color.copy(alpha = alpha))
+                }
+            }
+        }
+    }
+
     override fun onDispose() {
-        effects.fastForEach { it.dispose() }
-        effects.clear()
-        currentEffect = null
+        ripples.clear()
+        currentRipple = null
+    }
+}
+
+private class StateLayer(
+    clock: AnimationClockObservable,
+    private val bounded: Boolean,
+    private val rippleOpacity: RippleOpacity
+) {
+    private val animatedOpacity = AnimatedFloatModel(0f, clock)
+    private var previousInteractions: Set<Interaction> = emptySet()
+    private var lastDrawnInteraction: Interaction? = null
+
+    fun ContentDrawScope.drawStateLayer(
+        interactionState: InteractionState,
+        targetRadius: Float,
+        color: Color
+    ) {
+        val currentInteractions = interactionState.value
+        var handled = false
+
+        // Handle a new interaction
+        for (interaction in currentInteractions) {
+            // Stop looping if we have already moved to a new state
+            if (handled) break
+
+            // Move to the next interaction if this interaction is not a new interaction
+            if (interaction in previousInteractions) continue
+
+            // Pressed state is explicitly handled with a ripple animation, and not a state layer
+            if (interaction is Interaction.Pressed) continue
+
+            // Move to the next interaction if this is not an interaction we show a state layer for
+            val targetOpacity = rippleOpacity.opacityForInteraction(interaction)
+            if (targetOpacity == 0f) continue
+
+            val animationBuilder = animationBuilderForInteraction(interaction)
+            animatedOpacity.animateTo(
+                targetOpacity,
+                animationBuilder
+            )
+
+            lastDrawnInteraction = interaction
+            handled = true
+        }
+
+        // Clean up any stale interactions if we have not moved to a new interaction
+        if (!handled) {
+            val previousInteraction = lastDrawnInteraction
+            if (previousInteraction != null && previousInteraction !in currentInteractions) {
+                animatedOpacity.animateTo(
+                    0f,
+                    animationBuilderForInteraction(previousInteraction)
+                )
+
+                lastDrawnInteraction = null
+            }
+        }
+
+        previousInteractions = currentInteractions
+
+        val modulatedColor = color.copy(alpha = animatedOpacity.value)
+
+        if (animatedOpacity.value > 0f) {
+            if (bounded) {
+                clipRect {
+                    drawCircle(modulatedColor, targetRadius)
+                }
+            } else {
+                drawCircle(modulatedColor, targetRadius)
+            }
+        }
+    }
+
+    /**
+     * TODO: handle [interaction] for hover / focus states
+     */
+    @Suppress("UNUSED_PARAMETER")
+    private fun animationBuilderForInteraction(interaction: Interaction): AnimationBuilder<Float> {
+        return TweenBuilder<Float>().apply {
+            duration = 15
+            easing = LinearEasing
+        }
     }
 }
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleTheme.kt b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleTheme.kt
index 5bb17ef..ccfa3a5 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleTheme.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ripple/RippleTheme.kt
@@ -18,44 +18,138 @@
 
 import androidx.compose.Composable
 import androidx.compose.staticAmbientOf
+import androidx.ui.foundation.Interaction
 import androidx.ui.foundation.contentColor
 import androidx.ui.graphics.Color
+import androidx.ui.graphics.luminance
 import androidx.ui.material.MaterialTheme
 
 /**
- * Defines the appearance and the behavior for [ripple]s.
+ * Defines the appearance and the behavior for [RippleIndication]s.
  *
- * You can define new theme and apply it via [RippleThemeAmbient].
+ * You can define a new theme and apply it via [RippleThemeAmbient].
  */
-data class RippleTheme(
+interface RippleTheme {
     /**
-     * Defines the current [RippleEffect] implementation.
+     * @return the default [RippleIndication] color at the call site's position in the hierarchy.
+     * This color will be used when a color is not explicitly set in the [RippleIndication] itself.
      */
-    val factory: RippleEffectFactory,
+    @Composable
+    fun defaultColor(): Color
+
     /**
-     * The effect that will be used to calculate the [ripple] color when it is not explicitly
-     * set in a [ripple].
+     * @return the [RippleOpacity] used to calculate the opacity for the ripple depending on the
+     * [Interaction] for a given component. This will be set as the alpha channel for
+     * [defaultColor] or the color explicitly provided to the [RippleIndication].
      */
-    val defaultColor: @Composable () -> Color,
+    @Composable
+    fun rippleOpacity(): RippleOpacity
+}
+
+// TODO: can be a fun interface when we rebase to use Kotlin 1.4
+/**
+ * RippleOpacity defines the opacity of the ripple / state layer for a given [Interaction].
+ */
+interface RippleOpacity {
     /**
-     * The effect that will be used to calculate the opacity applied to the [ripple] color.
-     * For example, it can be different in dark and light modes.
+     * @return the opacity of the ripple for the given [interaction]. Return `0f` if this
+     * particular interaction should not show a corresponding ripple / state layer.
      */
-    val opacity: @Composable () -> Float
-)
+    fun opacityForInteraction(interaction: Interaction): Float
+}
 
 /**
  * Ambient used for providing [RippleTheme] down the tree.
  */
-val RippleThemeAmbient = staticAmbientOf { DefaultRippleTheme }
+val RippleThemeAmbient = staticAmbientOf<RippleTheme> { DefaultRippleTheme }
 
-private val DefaultRippleTheme = RippleTheme(
-    factory = DefaultRippleEffectFactory,
-    defaultColor = { contentColor() },
-    opacity = {
-        if (MaterialTheme.colors.isLight) LightRippleOpacity else DarkRippleOpacity
+private object DefaultRippleTheme : RippleTheme {
+    @Composable
+    override fun defaultColor(): Color {
+        val contentColor = contentColor()
+        val lightTheme = MaterialTheme.colors.isLight
+        val contentLuminance = contentColor.luminance()
+        // If we are on a colored surface (typically indicated by low luminance content), the
+        // ripple color should be white.
+        return if (!lightTheme && contentLuminance < 0.5) {
+            Color.White
+            // Otherwise use contentColor
+        } else {
+            contentColor
+        }
     }
+
+    @Composable
+    override fun rippleOpacity(): RippleOpacity {
+        val lightTheme = MaterialTheme.colors.isLight
+        val contentLuminance = contentColor().luminance()
+        return when {
+            lightTheme -> {
+                if (contentLuminance > 0.5) {
+                    LightThemeHighContrastRippleOpacity
+                } else {
+                    LightThemeReducedContrastRippleOpacity
+                }
+            }
+            else -> {
+                DarkThemeRippleOpacity
+            }
+        }
+    }
+}
+
+@Suppress("unused")
+private sealed class DefaultRippleOpacity(
+    val pressed: Float,
+    val focused: Float,
+    val dragged: Float,
+    val hovered: Float
+) : RippleOpacity {
+    override fun opacityForInteraction(interaction: Interaction): Float = when (interaction) {
+        Interaction.Pressed -> pressed
+        Interaction.Dragged -> dragged
+        else -> 0f
+    }
+}
+
+/**
+ * Opacity values for high luminance content in a light theme.
+ *
+ * This content will typically be placed on colored surfaces, so it is important that the
+ * contrast here is higher to meet accessibility standards, and increase legibility.
+ *
+ * These levels are typically used for text / iconography in primary colored tabs /
+ * bottom navigation / etc.
+ */
+private object LightThemeHighContrastRippleOpacity : DefaultRippleOpacity(
+    pressed = 0.24f,
+    focused = 0.24f,
+    dragged = 0.16f,
+    hovered = 0.08f
 )
 
-private const val LightRippleOpacity = 0.12f
-private const val DarkRippleOpacity = 0.24f
+/**
+ * Alpha levels for low luminance content in a light theme.
+ *
+ * This content will typically be placed on grayscale surfaces, so the contrast here can be lower
+ * without sacrificing accessibility and legibility.
+ *
+ * These levels are typically used for body text on the main surface (white in light theme, grey
+ * in dark theme) and text / iconography in surface colored tabs / bottom navigation / etc.
+ */
+private object LightThemeReducedContrastRippleOpacity : DefaultRippleOpacity(
+    pressed = 0.12f,
+    focused = 0.12f,
+    dragged = 0.08f,
+    hovered = 0.04f
+)
+
+/**
+ * Alpha levels for all content in a dark theme.
+ */
+private object DarkThemeRippleOpacity : DefaultRippleOpacity(
+    pressed = 0.10f,
+    focused = 0.12f,
+    dragged = 0.08f,
+    hovered = 0.04f
+)
diff --git a/ui/ui-material/src/test/java/androidx/ui/material/ripple/DefaultRippleEffectTest.kt b/ui/ui-material/src/test/java/androidx/ui/material/ripple/RippleAnimationTest.kt
similarity index 90%
rename from ui/ui-material/src/test/java/androidx/ui/material/ripple/DefaultRippleEffectTest.kt
rename to ui/ui-material/src/test/java/androidx/ui/material/ripple/RippleAnimationTest.kt
index 041e48b..e4777d4 100644
--- a/ui/ui-material/src/test/java/androidx/ui/material/ripple/DefaultRippleEffectTest.kt
+++ b/ui/ui-material/src/test/java/androidx/ui/material/ripple/RippleAnimationTest.kt
@@ -18,7 +18,6 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.PxSize
 import androidx.ui.unit.dp
-import androidx.ui.unit.px
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -26,11 +25,11 @@
 import kotlin.math.sqrt
 
 @RunWith(JUnit4::class)
-class DefaultRippleEffectTest {
+class RippleAnimationTest {
 
     @Test
     fun testStartRadius() {
-        val size = PxSize(10.px, 30.px)
+        val size = PxSize(10f, 30f)
         val expectedRadius = 9.0f // 30% of 30
 
         // Top-level functions are not resolved properly in IR modules
@@ -42,7 +41,7 @@
     fun testEndRadiusBounded() {
         val width = 100f
         val height = 160f
-        val size = PxSize(width.px, height.px)
+        val size = PxSize(width, height)
         val density = Density(2f)
         val expectedRadius = with(density) {
             // 10 is an extra offset from spec
@@ -56,7 +55,7 @@
     fun testEndRadiusUnbounded() {
         val width = 140f
         val height = 100f
-        val size = PxSize(width.px, height.px)
+        val size = PxSize(width, height)
         val expectedRadius = halfDistance(width, height)
         val result = with(Density(1f)) { getRippleEndRadius(false, size) }
         assertThat(result).isEqualTo(expectedRadius)
diff --git a/ui/ui-test/api/0.1.0-dev14.txt b/ui/ui-test/api/0.1.0-dev14.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/0.1.0-dev14.txt
+++ b/ui/ui-test/api/0.1.0-dev14.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/api/api_lint.ignore b/ui/ui-test/api/api_lint.ignore
index b999d45..bf1c5cd 100644
--- a/ui/ui-test/api/api_lint.ignore
+++ b/ui/ui-test/api/api_lint.ignore
@@ -1,3 +1,7 @@
 // Baseline format: 1.0
 MissingNullability: androidx.ui.test.android.AndroidComposeTestRuleKt#AndroidComposeTestRule(androidx.compose.Recomposer, boolean):
     Missing nullability on method `AndroidComposeTestRule` return
+
+
+ReferencesDeprecated: androidx.ui.test.android.AndroidComposeTestRule#getActivityTestRule():
+    Return type of deprecated type androidx.test.rule.ActivityTestRule<T> in androidx.ui.test.android.AndroidComposeTestRule.getActivityTestRule(): this method should also be deprecated
diff --git a/ui/ui-test/api/current.txt b/ui/ui-test/api/current.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/current.txt
+++ b/ui/ui-test/api/current.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-test/api/public_plus_experimental_0.1.0-dev14.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-test/api/public_plus_experimental_0.1.0-dev14.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/api/public_plus_experimental_current.txt b/ui/ui-test/api/public_plus_experimental_current.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/public_plus_experimental_current.txt
+++ b/ui/ui-test/api/public_plus_experimental_current.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/api/restricted_0.1.0-dev14.txt b/ui/ui-test/api/restricted_0.1.0-dev14.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-test/api/restricted_0.1.0-dev14.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/api/restricted_current.txt b/ui/ui-test/api/restricted_current.txt
index 1fd1a3a..362e0bd 100644
--- a/ui/ui-test/api/restricted_current.txt
+++ b/ui/ui-test/api/restricted_current.txt
@@ -57,7 +57,7 @@
     method public static void assertShape-t2RoSCg(android.graphics.Bitmap, androidx.ui.unit.Density density, androidx.ui.graphics.Shape shape, long shapeColor, long backgroundColor, androidx.ui.graphics.Shape backgroundShape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, float sizeX = width.toFloat(), float sizeY = height.toFloat(), float shapeSizeX = sizeX, float shapeSizeY = sizeY, float centerX = width / 2.0, float centerY = height / 2.0, float shapeOverlapPixelCount = 1.0f);
     method public static android.graphics.Bitmap captureToBitmap(androidx.ui.test.SemanticsNodeInteraction);
     method public static android.graphics.Bitmap captureToBitmap(android.view.View);
-    method public static boolean contains-m3TnucA(androidx.ui.graphics.Path, long offset);
+    method public static boolean contains(androidx.ui.graphics.Path, androidx.ui.geometry.Offset offset);
   }
 
   public final class CollectedSizes {
@@ -199,30 +199,30 @@
   }
 
   public final class GestureScopeKt {
-    method public static androidx.ui.unit.PxPosition getCenter(androidx.ui.test.BaseGestureScope);
+    method public static androidx.ui.geometry.Offset getCenter(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.PxBounds getGlobalBounds(androidx.ui.test.BaseGestureScope);
     method public static androidx.ui.unit.IntPxSize getSize(androidx.ui.test.BaseGestureScope);
-    method public static androidx.ui.unit.PxPosition localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
+    method public static androidx.ui.geometry.Offset localToGlobal(androidx.ui.test.BaseGestureScope, androidx.ui.geometry.Offset position);
+    method public static void movePointerBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void movePointerTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
     method public static void sendCancel(androidx.ui.test.PartialGestureScope);
-    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition position = center);
+    method public static void sendClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDoubleClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendDown(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendLongClick(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset position = center);
     method public static void sendMove(androidx.ui.test.PartialGestureScope);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition delta);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.unit.PxPosition position);
-    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.unit.PxPosition position);
-    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start0, androidx.ui.unit.PxPosition end0, androidx.ui.unit.PxPosition start1, androidx.ui.unit.PxPosition end1, androidx.ui.unit.Duration duration = 400.milliseconds);
-    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveBy(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset delta);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, int pointerId, androidx.ui.geometry.Offset position);
+    method public static void sendMoveTo(androidx.ui.test.PartialGestureScope, androidx.ui.geometry.Offset position);
+    method public static void sendPinch(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start0, androidx.ui.geometry.Offset end0, androidx.ui.geometry.Offset start1, androidx.ui.geometry.Offset end1, androidx.ui.unit.Duration duration = 400.milliseconds);
+    method public static void sendSwipe(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendSwipeDown(androidx.ui.test.GestureScope);
     method public static void sendSwipeLeft(androidx.ui.test.GestureScope);
     method public static void sendSwipeRight(androidx.ui.test.GestureScope);
     method public static void sendSwipeUp(androidx.ui.test.GestureScope);
-    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
+    method public static void sendSwipeWithVelocity(androidx.ui.test.GestureScope, androidx.ui.geometry.Offset start, androidx.ui.geometry.Offset end, @FloatRange(from=0.0) float endVelocity, androidx.ui.unit.Duration duration = 200.milliseconds);
     method public static void sendUp(androidx.ui.test.PartialGestureScope, int pointerId = 0);
   }
 
diff --git a/ui/ui-test/src/androidTest/AndroidManifest.xml b/ui/ui-test/src/androidTest/AndroidManifest.xml
index 12873b1..6ec2ae6 100644
--- a/ui/ui-test/src/androidTest/AndroidManifest.xml
+++ b/ui/ui-test/src/androidTest/AndroidManifest.xml
@@ -21,7 +21,7 @@
             android:theme="@style/TestTheme"/>
         <activity android:name="androidx.ui.test.CustomActivity"
             android:theme="@android:style/Theme.Material.NoActionBar.Fullscreen"/>
-        <activity android:name="androidx.ui.test.gesturescope.ActivityWithActionBar" />
+        <activity android:name="androidx.ui.test.ActivityWithActionBar" />
         <activity android:name="androidx.ui.test.MultipleActivitiesFindTest$Activity1" />
         <activity android:name="androidx.ui.test.MultipleActivitiesFindTest$Activity2" />
         <activity android:name="androidx.ui.test.MultipleActivitiesClickTest$Activity1" />
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/ActivityWithActionBar.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/ActivityWithActionBar.kt
new file mode 100644
index 0000000..4946a2c
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/ActivityWithActionBar.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.test
+
+import android.os.Bundle
+import android.view.Gravity
+import android.widget.FrameLayout
+import androidx.activity.ComponentActivity
+import androidx.compose.Composable
+import androidx.compose.Recomposer
+import androidx.ui.core.setContent
+
+// The presence of an ActionBar follows from the theme set in AndroidManifest.xml
+class ActivityWithActionBar : ComponentActivity() {
+    private lateinit var composeHolder: FrameLayout
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val root = FrameLayout(this)
+        composeHolder = FrameLayout(this).apply {
+            layoutParams = FrameLayout.LayoutParams(100, 100).apply {
+                gravity = Gravity.BOTTOM or Gravity.END
+            }
+            // Set background color for recognizability on screen / in screenshots
+            setBackgroundColor(android.graphics.Color.LTGRAY)
+        }
+        root.addView(composeHolder)
+        setContentView(root)
+    }
+
+    fun setContent(composable: @Composable () -> Unit) {
+        composeHolder.setContent(Recomposer.current(), composable)
+    }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt
index 75c4e0b5..4dab2cf 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/BitmapCapturingTest.kt
@@ -18,7 +18,6 @@
 
 import androidx.activity.ComponentActivity
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Modifier
 import androidx.ui.core.testTag
 import androidx.ui.foundation.Box
@@ -30,7 +29,6 @@
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredSize
 import androidx.ui.test.android.AndroidComposeTestRule
-import androidx.ui.test.gesturescope.ActivityWithActionBar
 import androidx.ui.unit.IntPxPosition
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.ipx
@@ -56,8 +54,11 @@
         )
     }
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val composeTestRule = AndroidComposeTestRule(ActivityTestRule(config.activityClass))
+    val composeTestRule = AndroidComposeTestRule(
+        androidx.test.rule.ActivityTestRule(config.activityClass)
+    )
 
     private val rootTag = "Root"
     private val tag11 = "Rect11"
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/AnimationSynchronizationTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/ComposeIdlingResourceTest.kt
similarity index 96%
rename from ui/ui-test/src/androidTest/java/androidx/ui/test/AnimationSynchronizationTest.kt
rename to ui/ui-test/src/androidTest/java/androidx/ui/test/ComposeIdlingResourceTest.kt
index e0ab1a6..b4ddc24 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/AnimationSynchronizationTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/ComposeIdlingResourceTest.kt
@@ -40,15 +40,14 @@
 import org.junit.Rule
 import org.junit.Test
 
-private const val nonIdleDuration = 1000L
-
-private const val animateFromX = 0f
-private const val animateToX = 50f
-
-private val rectSize = Size(50.0f, 50.0f)
-
 @LargeTest
-class AnimationSynchronizationTest {
+class ComposeIdlingResourceTest {
+    companion object {
+        private const val nonIdleDuration = 1000L
+        private const val animateFromX = 0f
+        private const val animateToX = 50f
+        private val rectSize = Size(50.0f, 50.0f)
+    }
 
     private val handler = Handler(Looper.getMainLooper())
 
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 65a8f4a..a8eb8f3 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
@@ -27,7 +27,7 @@
 import androidx.ui.layout.Column
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.preferredWidth
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.dp
 import androidx.ui.unit.ipx
 import org.junit.Assert.assertEquals
@@ -69,8 +69,8 @@
 
         assertTrue(latch.await(1, TimeUnit.SECONDS))
         assertEquals(
-            PxPosition.Origin,
-            parentCoordinates!!.childToLocal(childCoordinates!!, PxPosition.Origin)
+            Offset.Zero,
+            parentCoordinates!!.childToLocal(childCoordinates!!, Offset.Zero)
         )
     }
 
@@ -104,8 +104,8 @@
 
         assertTrue(latch.await(1, TimeUnit.SECONDS))
         assertEquals(
-            PxPosition(5f, 0f),
-            parentCoordinates!!.childToLocal(childCoordinates!!, PxPosition.Origin)
+            Offset(5f, 0f),
+            parentCoordinates!!.childToLocal(childCoordinates!!, Offset.Zero)
         )
     }
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
index 6cdb80f..2da4e4c 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendClickTest.kt
@@ -16,20 +16,15 @@
 
 package androidx.ui.test.gesturescope
 
-import android.os.Bundle
-import android.view.Gravity
-import android.widget.FrameLayout
 import androidx.activity.ComponentActivity
 import androidx.compose.Composable
-import androidx.compose.Recomposer
 import androidx.test.filters.MediumTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.changedToUp
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
-import androidx.ui.core.setContent
 import androidx.ui.graphics.Color
 import androidx.ui.layout.Column
+import androidx.ui.test.ActivityWithActionBar
 import androidx.ui.test.android.AndroidComposeTestRule
 import androidx.ui.test.doGesture
 import androidx.ui.test.findByTag
@@ -38,64 +33,108 @@
 import androidx.ui.test.sendClick
 import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.RecordingFilter
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-private const val tag = "widget"
-private const val numberOfSquares = 5
-private const val first = 0
-private const val last = numberOfSquares - 1
-private const val squareSize = 10.0f
-private val center = PxPosition(squareSize / 2, squareSize / 2)
-private val colors = listOf(Color.Red, Color.Yellow, Color.Blue, Color.Green, Color.Cyan)
+@MediumTest
+@RunWith(Parameterized::class)
+class SendClickTest(private val config: TestConfig) {
+    data class TestConfig(
+        val position: Offset?,
+        val activityClass: Class<out ComponentActivity>
+    )
 
-private data class ClickData(
-    val componentIndex: Int,
-    val position: PxPosition
-)
+    companion object {
+        private const val squareSize = 10.0f
+        private val colors = listOf(Color.Red, Color.Yellow, Color.Blue, Color.Green, Color.Cyan)
 
-private class ClickRecorder(
-    private val componentIndex: Int,
-    private val recordedClicks: MutableList<ClickData>
-) : PointerInputModifier {
-    override val pointerInputFilter: PointerInputFilter = RecordingFilter { changes ->
-        changes.forEach {
-            if (it.changedToUp()) {
-                recordedClicks.add(ClickData(componentIndex, it.current.position!!))
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun createTestSet(): List<TestConfig> {
+            return mutableListOf<TestConfig>().apply {
+                for (x in listOf(0.0f, squareSize - 1.0f)) {
+                    for (y in listOf(0.0f, squareSize - 1.0f)) {
+                        add(TestConfig(Offset(x, y), ComponentActivity::class.java))
+                        add(TestConfig(Offset(x, y), ActivityWithActionBar::class.java))
+                    }
+                }
+                add(TestConfig(null, ComponentActivity::class.java))
+                add(TestConfig(null, ActivityWithActionBar::class.java))
             }
         }
     }
-}
 
-// The presence of an ActionBar follows from the theme set in AndroidManifest.xml
-class ActivityWithActionBar : ComponentActivity() {
-    private lateinit var composeHolder: FrameLayout
+    private data class ClickData(
+        val componentIndex: Int,
+        val position: Offset
+    )
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        val root = FrameLayout(this)
-        composeHolder = FrameLayout(this).apply {
-            layoutParams = FrameLayout.LayoutParams(100, 100).apply {
-                gravity = Gravity.BOTTOM or Gravity.END
+    private class ClickRecorder(
+        private val componentIndex: Int,
+        private val recordedClicks: MutableList<ClickData>
+    ) : PointerInputModifier {
+        override val pointerInputFilter: PointerInputFilter = RecordingFilter { changes ->
+            changes.forEach {
+                if (it.changedToUp()) {
+                    recordedClicks.add(ClickData(componentIndex, it.current.position!!))
+                }
             }
-            // Set background color for recognizability on screen / in screenshots
-            setBackgroundColor(android.graphics.Color.LTGRAY)
         }
-        root.addView(composeHolder)
-        setContentView(root)
     }
 
-    fun setContent(composable: @Composable () -> Unit) {
-        composeHolder.setContent(Recomposer.current(), composable)
-    }
-}
+    @Suppress("DEPRECATION")
+    @get:Rule
+    val composeTestRule = AndroidComposeTestRule(
+        androidx.test.rule.ActivityTestRule(config.activityClass),
+        disableTransitions = true
+    )
 
-private fun AndroidComposeTestRule<*>.setContent(recordedClicks: MutableList<ClickData>) {
-    val content = @Composable {
+    private val recordedClicks = mutableListOf<ClickData>()
+    private val expectedClickPosition =
+        config.position ?: Offset(squareSize / 2, squareSize / 2)
+
+    @Test
+    fun testClick() {
+        // Given a column of 5 small components
+        val activity = composeTestRule.activityTestRule.activity
+        if (activity is ActivityWithActionBar) {
+            runOnUiThread { activity.setContent { ColumnOfSquares(5) } }
+        } else {
+            composeTestRule.setContent { ColumnOfSquares(5) }
+        }
+
+        // When I click the first and last of these components
+        click("square0")
+        click("square4")
+
+        // Then those components have registered a click
+        runOnIdleCompose {
+            assertThat(recordedClicks).isEqualTo(
+                listOf(
+                    ClickData(0, expectedClickPosition),
+                    ClickData(4, expectedClickPosition)
+                )
+            )
+        }
+    }
+
+    private fun click(tag: String) {
+        findByTag(tag).doGesture {
+            if (config.position != null) {
+                sendClick(config.position)
+            } else {
+                sendClick()
+            }
+        }
+    }
+
+    @Composable
+    @Suppress("SameParameterValue")
+    private fun ColumnOfSquares(numberOfSquares: Int) {
         Column {
             repeat(numberOfSquares) { i ->
                 ClickableTestBox(
@@ -103,113 +142,9 @@
                     width = squareSize,
                     height = squareSize,
                     color = colors[i],
-                    tag = "$tag$i"
+                    tag = "square$i"
                 )
             }
         }
     }
-
-    val activity = activityTestRule.activity
-    if (activity is ActivityWithActionBar) {
-        runOnUiThread {
-            activity.setContent(content)
-        }
-    } else {
-        setContent(content)
-    }
-}
-
-@MediumTest
-@RunWith(Parameterized::class)
-class SendClickWithoutArgumentsTest(config: TestConfig) {
-    data class TestConfig(
-        val activityClass: Class<out ComponentActivity>
-    )
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun createTestSet(): List<TestConfig> = listOf(
-            TestConfig(ComponentActivity::class.java),
-            TestConfig(ActivityWithActionBar::class.java)
-        )
-    }
-
-    @get:Rule
-    val composeTestRule = AndroidComposeTestRule(
-        ActivityTestRule(config.activityClass),
-        disableTransitions = true
-    )
-
-    @Test
-    fun testClickWithoutArguments() {
-        // Given a column of 5 small components
-        val recordedClicks = mutableListOf<ClickData>()
-        composeTestRule.setContent(recordedClicks)
-
-        // When I click the first and last of these components
-        findByTag("$tag$first").doGesture { sendClick() }
-        findByTag("$tag$last").doGesture { sendClick() }
-
-        // Then those components have registered a click
-        runOnIdleCompose {
-            assertThat(recordedClicks).isEqualTo(
-                listOf(
-                    ClickData(first, center),
-                    ClickData(last, center)
-                )
-            )
-        }
-    }
-}
-
-@MediumTest
-@RunWith(Parameterized::class)
-class SendClickWithArgumentsTest(private val config: TestConfig) {
-    data class TestConfig(
-        val position: PxPosition,
-        val activityClass: Class<out ComponentActivity>
-    )
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun createTestSet(): List<TestConfig> {
-            return mutableListOf<TestConfig>().apply {
-                for (x in listOf(0.0f, squareSize - 1.0f)) {
-                    for (y in listOf(0.0f, squareSize - 1.0f)) {
-                        add(TestConfig(PxPosition(x, y), ComponentActivity::class.java))
-                        add(TestConfig(PxPosition(x, y), ActivityWithActionBar::class.java))
-                    }
-                }
-            }
-        }
-    }
-
-    @get:Rule
-    val composeTestRule = AndroidComposeTestRule(
-        ActivityTestRule(config.activityClass),
-        disableTransitions = true
-    )
-
-    @Test
-    fun testClickWithArguments() {
-        // Given a column of 5 small components
-        val recordedClicks = mutableListOf<ClickData>()
-        composeTestRule.setContent(recordedClicks)
-
-        // When I click the first and last of these components
-        findByTag("$tag$first").doGesture { sendClick(config.position) }
-        findByTag("$tag$last").doGesture { sendClick(config.position) }
-
-        // Then those components have registered a click
-        runOnIdleCompose {
-            assertThat(recordedClicks).isEqualTo(
-                listOf(
-                    ClickData(first, config.position),
-                    ClickData(last, config.position)
-                )
-            )
-        }
-    }
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
index 25ce7fa..fff7ddc 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendDoubleClickTest.kt
@@ -28,7 +28,7 @@
 import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.ClickableTestBox.defaultSize
 import androidx.ui.test.util.ClickableTestBox.defaultTag
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -37,44 +37,9 @@
 import org.junit.runners.Parameterized
 
 @MediumTest
-class SendDoubleClickWithoutArgumentsTest {
-
-    @get:Rule
-    val composeTestRule = createComposeRule(disableTransitions = true)
-
-    @get:Rule
-    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
-        disableDispatchInRealTime = true
-    )
-
-    private val recordedDoubleClicks = mutableListOf<PxPosition>()
-    private val expectedClickPosition = PxPosition(defaultSize / 2, defaultSize / 2)
-
-    private fun recordDoubleClick(position: PxPosition) {
-        recordedDoubleClicks.add(position)
-    }
-
-    @Test
-    fun testDoubleClick() {
-        // Given some content
-        composeTestRule.setContent {
-            ClickableTestBox(Modifier.doubleTapGestureFilter(this::recordDoubleClick))
-        }
-
-        // When we inject a double click
-        findByTag(defaultTag).doGesture { sendDoubleClick() }
-
-        runOnIdleCompose {
-            // Then we record 1 double click at the expected position
-            assertThat(recordedDoubleClicks).isEqualTo(listOf(expectedClickPosition))
-        }
-    }
-}
-
-@MediumTest
 @RunWith(Parameterized::class)
-class SendDoubleClickWithArgumentsTest(private val config: TestConfig) {
-    data class TestConfig(val position: PxPosition)
+class SendDoubleClickTest(private val config: TestConfig) {
+    data class TestConfig(val position: Offset?)
 
     companion object {
         @JvmStatic
@@ -83,9 +48,10 @@
             return mutableListOf<TestConfig>().apply {
                 for (x in listOf(1.0f, 33.0f, 99.0f)) {
                     for (y in listOf(1.0f, 33.0f, 99.0f)) {
-                        add(TestConfig(PxPosition(x, y)))
+                        add(TestConfig(Offset(x, y)))
                     }
                 }
+                add(TestConfig(null))
             }
         }
     }
@@ -98,22 +64,29 @@
         disableDispatchInRealTime = true
     )
 
-    private val recordedDoubleClicks = mutableListOf<PxPosition>()
-    private val expectedClickPosition = config.position
+    private val recordedDoubleClicks = mutableListOf<Offset>()
+    private val expectedClickPosition =
+        config.position ?: Offset(defaultSize / 2, defaultSize / 2)
 
-    private fun recordDoubleClick(position: PxPosition) {
+    private fun recordDoubleClick(position: Offset) {
         recordedDoubleClicks.add(position)
     }
 
     @Test
-    fun testDoubleClickOnPosition() {
+    fun testDoubleClick() {
         // Given some content
         composeTestRule.setContent {
             ClickableTestBox(Modifier.doubleTapGestureFilter(this::recordDoubleClick))
         }
 
         // When we inject a double click
-        findByTag(defaultTag).doGesture { sendDoubleClick(config.position) }
+        findByTag(defaultTag).doGesture {
+            if (config.position != null) {
+                sendDoubleClick(config.position)
+            } else {
+                sendDoubleClick()
+            }
+        }
 
         runOnIdleCompose {
             // Then we record 1 double click at the expected position
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
index 9843083..def81a7 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendLongClickTest.kt
@@ -31,61 +31,22 @@
 import androidx.ui.test.util.ClickableTestBox.defaultSize
 import androidx.ui.test.util.ClickableTestBox.defaultTag
 import androidx.ui.test.util.isAlmostEqualTo
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
 import org.junit.runners.Parameterized
 
 /**
- * Tests [sendLongClick] without arguments. Verifies that the click is in the middle
- * of the component, that the gesture has a duration of 600 milliseconds and that all input
- * events were on the same location.
- */
-@MediumTest
-@RunWith(JUnit4::class)
-class SendLongClickWithoutArgumentsTest {
-
-    @get:Rule
-    val composeTestRule = createComposeRule(disableTransitions = true)
-
-    private val recordedLongClicks = mutableListOf<PxPosition>()
-    private val expectedPosition = PxPosition(defaultSize / 2, defaultSize / 2)
-
-    private fun recordLongPress(position: PxPosition) {
-        recordedLongClicks.add(position)
-    }
-
-    @Test
-    fun testLongClick() {
-        // Given some content
-        composeTestRule.setContent {
-            Stack(Modifier.fillMaxSize().wrapContentSize(Alignment.BottomEnd)) {
-                ClickableTestBox(Modifier.longPressGestureFilter(::recordLongPress))
-            }
-        }
-
-        // When we inject a long click
-        findByTag(defaultTag).doGesture { sendLongClick() }
-
-        // Then we record 1 long click at the expected position
-        assertThat(recordedLongClicks).isEqualTo(listOf(expectedPosition))
-    }
-}
-
-/**
  * Tests [sendLongClick] with arguments. Verifies that the click is in the middle
  * of the component, that the gesture has a duration of 600 milliseconds and that all input
  * events were on the same location.
  */
 @MediumTest
 @RunWith(Parameterized::class)
-class SendLongClickWithArgumentsTest(private val config: TestConfig) {
-    data class TestConfig(
-        val position: PxPosition
-    )
+class SendLongClickTest(private val config: TestConfig) {
+    data class TestConfig(val position: Offset?)
 
     companion object {
         @JvmStatic
@@ -94,9 +55,10 @@
             return mutableListOf<TestConfig>().apply {
                 for (x in listOf(1.0f, defaultSize / 4)) {
                     for (y in listOf(1.0f, defaultSize / 3)) {
-                        add(TestConfig(PxPosition(x, y)))
+                        add(TestConfig(Offset(x, y)))
                     }
                 }
+                add(TestConfig(null))
             }
         }
     }
@@ -104,9 +66,11 @@
     @get:Rule
     val composeTestRule = createComposeRule(disableTransitions = true)
 
-    private val recordedLongClicks = mutableListOf<PxPosition>()
+    private val recordedLongClicks = mutableListOf<Offset>()
+    private val expectedClickPosition =
+        config.position ?: Offset(defaultSize / 2, defaultSize / 2)
 
-    private fun recordLongPress(position: PxPosition) {
+    private fun recordLongPress(position: Offset) {
         recordedLongClicks.add(position)
     }
 
@@ -120,10 +84,16 @@
         }
 
         // When we inject a long click
-        findByTag(defaultTag).doGesture { sendLongClick(config.position) }
+        findByTag(defaultTag).doGesture {
+            if (config.position != null) {
+                sendLongClick(config.position)
+            } else {
+                sendLongClick()
+            }
+        }
 
         // Then we record 1 long click at the expected position
         assertThat(recordedLongClicks).hasSize(1)
-        recordedLongClicks[0].isAlmostEqualTo(config.position)
+        recordedLongClicks[0].isAlmostEqualTo(expectedClickPosition)
     }
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendPinchTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendPinchTest.kt
index 08ad767..8b1a4e0 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendPinchTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendPinchTest.kt
@@ -30,7 +30,7 @@
 import androidx.ui.test.util.MultiPointerInputRecorder
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.isMonotonicBetween
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -60,10 +60,10 @@
             }
         }
 
-        val start0 = PxPosition(40f, 50f)
-        val end0 = PxPosition(8f, 50f)
-        val start1 = PxPosition(60f, 50f)
-        val end1 = PxPosition(92f, 50f)
+        val start0 = Offset(40f, 50f)
+        val end0 = Offset(8f, 50f)
+        val start1 = Offset(60f, 50f)
+        val end1 = Offset(92f, 50f)
         val duration = 400.milliseconds
 
         findByTag(TAG).doGesture {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
index d1fea6a..55683cf 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeTest.kt
@@ -33,9 +33,11 @@
 import androidx.ui.test.sendSwipeUp
 import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.SinglePointerInputRecorder
+import androidx.ui.test.util.assertDecreasing
+import androidx.ui.test.util.assertIncreasing
 import androidx.ui.test.util.assertOnlyLastEventIsUp
+import androidx.ui.test.util.assertSame
 import androidx.ui.test.util.assertTimestampsAreIncreasing
-import com.google.common.collect.Ordering
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -112,61 +114,44 @@
             }
         }
     }
-}
 
-private fun SinglePointerInputRecorder.assertSwipeIsUp() {
-    // Must have at least two events to have a direction
-    assertThat(events.size).isAtLeast(2)
-    // Last event must be above first event
-    assertThat(events.last().position.y).isLessThan(events.first().position.y)
-    // All events in between only move up
-    events.map { it.position.x }.assertSame(tolerance = 0.001f)
-    events.map { it.position.y }.assertDecreasing()
-}
-
-private fun SinglePointerInputRecorder.assertSwipeIsDown() {
-    // Must have at least two events to have a direction
-    assertThat(events.size).isAtLeast(2)
-    // Last event must be below first event
-    assertThat(events.last().position.y).isGreaterThan(events.first().position.y)
-    // All events in between only move down
-    events.map { it.position.x }.assertSame(tolerance = 0.001f)
-    events.map { it.position.y }.assertIncreasing()
-}
-
-private fun SinglePointerInputRecorder.assertSwipeIsLeft() {
-    // Must have at least two events to have a direction
-    assertThat(events.size).isAtLeast(2)
-    // Last event must be to the left of first event
-    assertThat(events.last().position.x).isLessThan(events.first().position.x)
-    // All events in between only move to the left
-    events.map { it.position.x }.assertDecreasing()
-    events.map { it.position.y }.assertSame(tolerance = 0.001f)
-}
-
-private fun SinglePointerInputRecorder.assertSwipeIsRight() {
-    // Must have at least two events to have a direction
-    assertThat(events.size).isAtLeast(2)
-    // Last event must be to the right of first event
-    assertThat(events.last().position.x).isGreaterThan(events.first().position.x)
-    // All events in between only move to the right
-    events.map { it.position.x }.assertIncreasing()
-    events.map { it.position.y }.assertSame(tolerance = 0.001f)
-}
-
-private fun List<Float>.assertSame(tolerance: Float = 0f) {
-    if (size <= 1) {
-        return
+    private fun SinglePointerInputRecorder.assertSwipeIsUp() {
+        // Must have at least two events to have a direction
+        assertThat(events.size).isAtLeast(2)
+        // Last event must be above first event
+        assertThat(events.last().position.y).isLessThan(events.first().position.y)
+        // All events in between only move up
+        events.map { it.position.x }.assertSame(tolerance = 0.001f)
+        events.map { it.position.y }.assertDecreasing()
     }
-    val baseValue = first()
-    assertThat(min()).isWithin(tolerance).of(baseValue)
-    assertThat(max()).isWithin(tolerance).of(baseValue)
-}
 
-private fun <E : Comparable<E>> List<E>.assertIncreasing() {
-    assertThat(this).isInOrder(Ordering.natural<E>())
-}
+    private fun SinglePointerInputRecorder.assertSwipeIsDown() {
+        // Must have at least two events to have a direction
+        assertThat(events.size).isAtLeast(2)
+        // Last event must be below first event
+        assertThat(events.last().position.y).isGreaterThan(events.first().position.y)
+        // All events in between only move down
+        events.map { it.position.x }.assertSame(tolerance = 0.001f)
+        events.map { it.position.y }.assertIncreasing()
+    }
 
-private fun <E : Comparable<E>> List<E>.assertDecreasing() {
-    assertThat(this).isInOrder(Ordering.natural<E>().reverse<E>())
+    private fun SinglePointerInputRecorder.assertSwipeIsLeft() {
+        // Must have at least two events to have a direction
+        assertThat(events.size).isAtLeast(2)
+        // Last event must be to the left of first event
+        assertThat(events.last().position.x).isLessThan(events.first().position.x)
+        // All events in between only move to the left
+        events.map { it.position.x }.assertDecreasing()
+        events.map { it.position.y }.assertSame(tolerance = 0.001f)
+    }
+
+    private fun SinglePointerInputRecorder.assertSwipeIsRight() {
+        // Must have at least two events to have a direction
+        assertThat(events.size).isAtLeast(2)
+        // Last event must be to the right of first event
+        assertThat(events.last().position.x).isGreaterThan(events.first().position.x)
+        // All events in between only move to the right
+        events.map { it.position.x }.assertIncreasing()
+        events.map { it.position.y }.assertSame(tolerance = 0.001f)
+    }
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
index c9d20ec..4575b06 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/gesturescope/SendSwipeVelocityTest.kt
@@ -37,8 +37,7 @@
 import androidx.ui.test.util.isMonotonicBetween
 import androidx.ui.test.util.recordedDuration
 import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.getDistance
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.inMilliseconds
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -61,11 +60,11 @@
         val eventPeriod: Long
     )
 
-    enum class Direction(val from: PxPosition, val to: PxPosition) {
-        LeftToRight(PxPosition(boxStart, boxMiddle), PxPosition(boxEnd, boxMiddle)),
-        RightToLeft(PxPosition(boxEnd, boxMiddle), PxPosition(boxStart, boxMiddle)),
-        TopToBottom(PxPosition(boxMiddle, boxStart), PxPosition(boxMiddle, boxEnd)),
-        BottomToTop(PxPosition(boxMiddle, boxEnd), PxPosition(boxMiddle, boxStart))
+    enum class Direction(val from: Offset, val to: Offset) {
+        LeftToRight(Offset(boxStart, boxMiddle), Offset(boxEnd, boxMiddle)),
+        RightToLeft(Offset(boxEnd, boxMiddle), Offset(boxStart, boxMiddle)),
+        TopToBottom(Offset(boxMiddle, boxStart), Offset(boxMiddle, boxEnd)),
+        BottomToTop(Offset(boxMiddle, boxEnd), Offset(boxMiddle, boxStart))
     }
 
     companion object {
@@ -161,8 +160,7 @@
                 val actualVelocity = recordedVelocity.pixelsPerSecond
                 assertThat(actualVelocity.x).isWithin(.1f).of(expectedXVelocity)
                 assertThat(actualVelocity.y).isWithin(.1f).of(expectedYVelocity)
-                assertThat(actualVelocity.getDistance().value)
-                    .isWithin(velocity * 0.001f).of(velocity)
+                assertThat(actualVelocity.getDistance()).isWithin(velocity * 0.001f).of(velocity)
             }
         }
     }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/Common.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/Common.kt
index 268a078..bcd8bb5 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/Common.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/Common.kt
@@ -16,17 +16,17 @@
 
 package androidx.ui.test.inputdispatcher
 
+import androidx.ui.geometry.Offset
 import androidx.ui.test.InputDispatcher
 import androidx.ui.test.android.AndroidInputDispatcher
-import androidx.ui.unit.PxPosition
 import com.google.common.truth.Truth.assertThat
 
-internal fun AndroidInputDispatcher.sendDownAndCheck(pointerId: Int, position: PxPosition) {
+internal fun AndroidInputDispatcher.sendDownAndCheck(pointerId: Int, position: Offset) {
     sendDown(pointerId, position)
     assertThat(getCurrentPosition(pointerId)).isEqualTo(position)
 }
 
-internal fun AndroidInputDispatcher.movePointerAndCheck(pointerId: Int, position: PxPosition) {
+internal fun AndroidInputDispatcher.movePointerAndCheck(pointerId: Int, position: Offset) {
     movePointer(pointerId, position)
     assertThat(getCurrentPosition(pointerId)).isEqualTo(position)
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
index b6bc3ae..7319164 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/DelayTest.kt
@@ -23,7 +23,7 @@
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.util.MotionEventRecorder
 import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
@@ -55,7 +55,7 @@
     }
 
     companion object {
-        private val anyPosition = PxPosition.Origin
+        private val anyPosition = Offset.Zero
 
         @JvmStatic
         @Parameterized.Parameters(name = "{0}")
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
index 5a7bc27..c7a6aba 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendCancelTest.kt
@@ -20,13 +20,13 @@
 import android.view.MotionEvent.ACTION_DOWN
 import android.view.MotionEvent.ACTION_POINTER_DOWN
 import androidx.test.filters.SmallTest
+import androidx.ui.geometry.Offset
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.util.MotionEventRecorder
 import androidx.ui.test.util.assertHasValidEventTimes
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verifyEvent
 import androidx.ui.test.util.verifyPointer
-import androidx.ui.unit.PxPosition
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -44,8 +44,8 @@
         private const val pointer2 = 22
 
         // positions (used with corresponding pointerId: pointerX with positionX_Y)
-        private val position1_1 = PxPosition(11f, 11f)
-        private val position2_1 = PxPosition(21f, 21f)
+        private val position1_1 = Offset(11f, 11f)
+        private val position2_1 = Offset(21f, 21f)
     }
 
     private val dispatcherRule = AndroidInputDispatcher.TestRule(disableDispatchInRealTime = true)
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
index ca02532..7b876bf 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendClickTest.kt
@@ -22,7 +22,7 @@
 import androidx.ui.test.util.MotionEventRecorder
 import androidx.ui.test.util.assertHasValidEventTimes
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -60,7 +60,7 @@
     @get:Rule
     val inputDispatcherRule: TestRule = dispatcherRule
 
-    private val position = PxPosition(config.x, config.y)
+    private val position = Offset(config.x, config.y)
 
     private val recorder = MotionEventRecorder()
     private val subject = AndroidInputDispatcher(recorder::recordEvent)
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
index 9158540..81b0ea2 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendDownTest.kt
@@ -21,13 +21,13 @@
 import android.view.MotionEvent.ACTION_POINTER_DOWN
 import android.view.MotionEvent.ACTION_POINTER_UP
 import androidx.test.filters.SmallTest
+import androidx.ui.geometry.Offset
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.util.MotionEventRecorder
 import androidx.ui.test.util.assertHasValidEventTimes
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verifyEvent
 import androidx.ui.test.util.verifyPointer
-import androidx.ui.unit.PxPosition
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -47,13 +47,13 @@
         private const val pointer4 = 44
 
         // Positions (mostly used with corresponding pointerId: pointerX with positionX)
-        private val position1 = PxPosition(1f, 1f)
-        private val position2 = PxPosition(2f, 2f)
-        private val position3 = PxPosition(3f, 3f)
-        private val position4 = PxPosition(4f, 4f)
+        private val position1 = Offset(1f, 1f)
+        private val position2 = Offset(2f, 2f)
+        private val position3 = Offset(3f, 3f)
+        private val position4 = Offset(4f, 4f)
 
         // Single alternative for pointer1
-        private val position1_2 = PxPosition(12f, 12f)
+        private val position1_2 = Offset(12f, 12f)
     }
 
     private val dispatcherRule = AndroidInputDispatcher.TestRule(disableDispatchInRealTime = true)
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
index e4a9484..c3c573f 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendMoveTest.kt
@@ -28,7 +28,7 @@
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verifyEvent
 import androidx.ui.test.util.verifyPointer
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -47,14 +47,14 @@
         private const val pointer3 = 33
 
         // positions (used with corresponding pointerId: pointerX with positionX_Y)
-        private val position1_1 = PxPosition(11f, 11f)
-        private val position2_1 = PxPosition(21f, 21f)
-        private val position3_1 = PxPosition(31f, 31f)
+        private val position1_1 = Offset(11f, 11f)
+        private val position2_1 = Offset(21f, 21f)
+        private val position3_1 = Offset(31f, 31f)
 
-        private val position1_2 = PxPosition(12f, 12f)
-        private val position2_2 = PxPosition(22f, 22f)
+        private val position1_2 = Offset(12f, 12f)
+        private val position2_2 = Offset(22f, 22f)
 
-        private val position1_3 = PxPosition(13f, 13f)
+        private val position1_3 = Offset(13f, 13f)
     }
 
     private val dispatcherRule = AndroidInputDispatcher.TestRule(disableDispatchInRealTime = true)
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt
deleted file mode 100644
index 676a6a7..0000000
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeFunctionTest.kt
+++ /dev/null
@@ -1,337 +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.ui.test.inputdispatcher
-
-import android.view.MotionEvent.ACTION_DOWN
-import android.view.MotionEvent.ACTION_MOVE
-import android.view.MotionEvent.ACTION_UP
-import androidx.test.filters.SmallTest
-import androidx.ui.test.android.AndroidInputDispatcher
-import androidx.ui.test.util.MotionEventRecorder
-import androidx.ui.test.util.assertHasValidEventTimes
-import androidx.ui.test.util.between
-import androidx.ui.test.util.moveEvents
-import androidx.ui.test.util.relativeEventTimes
-import androidx.ui.test.util.relativeTime
-import androidx.ui.test.util.splitsDurationEquallyInto
-import androidx.ui.test.util.verify
-import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.inMilliseconds
-import androidx.ui.unit.milliseconds
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TestRule
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-private val curve = { t: Long ->
-    PxPosition(
-        t.toFloat(),
-        (-t).toFloat()
-    )
-}
-
-/**
- * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
- * function between two positions. Verifies if the generated MotionEvents for a gesture with a
- * given duration have the expected timestamps. The timestamps should divide the duration as
- * equally as possible with as close to [AndroidInputDispatcher.eventPeriod] between each
- * successive event as possible.
- */
-@SmallTest
-@RunWith(Parameterized::class)
-class SwipeWithDurationTest(private val config: TestConfig) {
-    data class TestConfig(
-        val duration: Duration,
-        val expectedTimestamps: List<Long>
-    )
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun createTestSet(): List<TestConfig> {
-            return listOf(
-                // With eventPeriod of 10.ms, 0 events is 0.ms and 1 event is 10.ms
-                // Even though 1.ms is closer to 0.ms than to 10.ms, split into 1 event as we
-                // must have at least 1 move event to have movement.
-                TestConfig(1.milliseconds, listOf(1)),
-                // With eventPeriod of 10.ms, 0 events is 0.ms and 1 event is 10.ms
-                // Split 7.ms in 1 event as 7.ms is closer to 10.ms than to 0.ms
-                TestConfig(7.milliseconds, listOf(7)),
-                // With eventPeriod of 10.ms, a duration of 10.ms is exactly 1 event
-                TestConfig(10.milliseconds, listOf(10)),
-                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
-                // Split 14.ms in 1 event as 14.ms is closer to 10.ms than to 20.ms
-                TestConfig(14.milliseconds, listOf(14)),
-                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
-                // 15.ms is as close to 10.ms as it is to 20.ms, in which case the larger number
-                // of events is preferred -> 2 events
-                TestConfig(15.milliseconds, listOf(8, 15)),
-                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
-                // Split 19.ms in 2 events as 19.ms is closer to 20.ms than to 10.ms
-                TestConfig(19.milliseconds, listOf(10, 19)),
-                // With eventPeriod of 10.ms, 2 events is 20.ms and 3 events is 30.ms
-                // Split 24.ms in 2 events as 24.ms is closer to 20.ms than to 30.ms
-                TestConfig(24.milliseconds, listOf(12, 24)),
-                // With eventPeriod of 10.ms, 2 events is 20.ms and 3 events is 30.ms
-                // 25.ms is as close to 20.ms as it is to 30.ms, in which case the larger number
-                // of events is preferred -> 3 events
-                TestConfig(25.milliseconds, listOf(8, 17, 25)),
-                // With eventPeriod of 10.ms, 9 event is 90.ms and 10 events is 100.ms
-                // Split 97.ms in 10 events as 97.ms is closer to 100.ms than to 90.ms
-                TestConfig(97.milliseconds, listOf(10, 19, 29, 39, 49, 58, 68, 78, 87, 97))
-            )
-        }
-    }
-
-    @get:Rule
-    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
-        disableDispatchInRealTime = true
-    )
-
-    private val recorder = MotionEventRecorder()
-    private val subject = AndroidInputDispatcher(recorder::recordEvent)
-
-    @After
-    fun tearDown() {
-        recorder.disposeEvents()
-    }
-
-    @Test
-    fun swipeWithDuration() {
-        // Given a swipe with a given duration
-        subject.sendSwipe(curve = curve, duration = config.duration)
-
-        // then
-        val expectedNumberOfMoveEvents = config.expectedTimestamps.size
-        recorder.assertHasValidEventTimes()
-        recorder.events.apply {
-            // down + up + #move
-            assertThat(size).isEqualTo(2 + expectedNumberOfMoveEvents)
-
-            val durationMs = config.duration.inMilliseconds()
-            // First is down, last is up
-            first().verify(curve, ACTION_DOWN, expectedRelativeTime = 0)
-            last().verify(curve, ACTION_UP, expectedRelativeTime = durationMs)
-            // In between are all move events with the expected timestamps
-            drop(1).zip(config.expectedTimestamps).forEach { (event, expectedTimestamp) ->
-                event.verify(curve, ACTION_MOVE, expectedRelativeTime = expectedTimestamp)
-            }
-        }
-    }
-}
-
-/**
- * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
- * function between two positions. Verifies if the generated MotionEvents for a gesture with a
- * given duration and a set of keyTimes have the expected timestamps. The timestamps should
- * include all keyTimes, and divide the duration between those keyTimes as equally as possible
- * with as close to [AndroidInputDispatcher.eventPeriod] between each successive event as possible.
- */
-@SmallTest
-@RunWith(Parameterized::class)
-class SwipeWithKeyTimesTest(private val config: TestConfig) {
-    data class TestConfig(
-        val duration: Duration,
-        val keyTimes: List<Long>,
-        val expectedTimestamps: List<Long>
-    )
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun createTestSet(): List<TestConfig> {
-            return listOf(
-                // 10.ms normally splits into 1 event, but here we add a keyTime that must yield
-                // an event at that time
-                TestConfig(10.milliseconds, listOf(1), listOf(1, 10)),
-                TestConfig(10.milliseconds, listOf(2), listOf(2, 10)),
-                TestConfig(10.milliseconds, listOf(3), listOf(3, 10)),
-                TestConfig(10.milliseconds, listOf(4), listOf(4, 10)),
-                TestConfig(10.milliseconds, listOf(5), listOf(5, 10)),
-                TestConfig(10.milliseconds, listOf(6), listOf(6, 10)),
-                TestConfig(10.milliseconds, listOf(7), listOf(7, 10)),
-                TestConfig(10.milliseconds, listOf(8), listOf(8, 10)),
-                TestConfig(10.milliseconds, listOf(9), listOf(9, 10)),
-                // With 2 keyTimes we expect to see both those keyTimes in the generated events
-                TestConfig(10.milliseconds, listOf(1, 9), listOf(1, 9, 10)),
-                // Same for 3 keyTimes
-                TestConfig(10.milliseconds, listOf(1, 5, 9), listOf(1, 5, 9, 10)),
-                // If two keyTimes are longer than eventPeriod apart from each other, that period
-                // must be split as usual (here: between 10 and 28)
-                TestConfig(30.milliseconds, listOf(5, 10, 28), listOf(5, 10, 19, 28, 30))
-            )
-        }
-    }
-
-    @get:Rule
-    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
-        disableDispatchInRealTime = true
-    )
-
-    private val recorder = MotionEventRecorder()
-    private val subject = AndroidInputDispatcher(recorder::recordEvent)
-
-    @Before
-    fun setUp() {
-        require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
-            "keyTimes needs to be sorted, not ${config.keyTimes}"
-        }
-    }
-
-    @After
-    fun tearDown() {
-        recorder.disposeEvents()
-    }
-
-    @Test
-    fun swipeWithKeyTimes() {
-        // Given a swipe with a given duration and set of keyTimes
-        subject.sendSwipe(curve = curve, duration = config.duration, keyTimes = config.keyTimes)
-
-        // then
-        val expectedNumberOfMoveEvents = config.expectedTimestamps.size
-        recorder.assertHasValidEventTimes()
-        recorder.events.apply {
-            // down + up + #move
-            assertThat(size).isEqualTo(2 + expectedNumberOfMoveEvents)
-
-            val durationMs = config.duration.inMilliseconds()
-            // First is down, last is up
-            first().verify(curve, ACTION_DOWN, expectedRelativeTime = 0)
-            last().verify(curve, ACTION_UP, expectedRelativeTime = durationMs)
-            // In between are all move events with the expected timestamps
-            drop(1).zip(config.expectedTimestamps).forEach { (event, expectedTimestamp) ->
-                event.verify(curve, ACTION_MOVE, expectedRelativeTime = expectedTimestamp)
-            }
-        }
-    }
-}
-
-/**
- * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
- * function between two positions. Verifies if the generated MotionEvents for a gesture with a
- * given duration and a set of keyTimes have the expected timestamps, if the event period would
- * be different. This is not a situation that can occur in practice, but is necessary to test to
- * ensure the calculations made by the [AndroidInputDispatcher] are correct.
- *
- * The timestamps of the generated events should include all keyTimes, and divide the duration
- * between those keyTimes as equally as possible with as close to [eventPeriod] between each
- * successive event as possible.
- *
- * This uses a different verification mechanism as the previous tests, because here we need to
- * calculate the expected timestamps.
- */
-@SmallTest
-@RunWith(Parameterized::class)
-class SendSwipeWithKeyTimesAndEventPeriodTest(private val config: TestConfig) {
-    data class TestConfig(
-        val duration: Duration,
-        val keyTimes: List<Long>,
-        val eventPeriod: Long
-    )
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun createTestSet(): List<TestConfig> {
-            return listOf(10L, 4L, 7L).flatMap { eventPeriod ->
-                // pick a prime number for duration
-                val durationMs = 101L
-                // testing all possible keyTimes between 0 and 100 takes way too long,
-                // only test several combinations keyTimes close to the middle instead
-                val firstKeyTime = (durationMs / 2) - eventPeriod
-                val lastKeyTime = (durationMs / 2) + eventPeriod
-                (firstKeyTime..lastKeyTime step eventPeriod).flatMap { keyTime1 ->
-                    (keyTime1..lastKeyTime).map { keyTime2 ->
-                        TestConfig(
-                            Duration(milliseconds = durationMs),
-                            listOf(keyTime1, keyTime2),
-                            eventPeriod
-                        )
-                    }
-                }
-            }
-        }
-    }
-
-    @get:Rule
-    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
-        disableDispatchInRealTime = true,
-        eventPeriodOverride = config.eventPeriod
-    )
-
-    private val duration get() = config.duration
-    private val keyTimes get() = config.keyTimes
-    private val eventPeriod = config.eventPeriod
-
-    private val recorder = MotionEventRecorder()
-    private val subject = AndroidInputDispatcher(recorder::recordEvent)
-
-    @Before
-    fun setUp() {
-        require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
-            "keyTimes needs to be sorted, not ${config.keyTimes}"
-        }
-    }
-
-    @After
-    fun tearDown() {
-        recorder.disposeEvents()
-    }
-
-    @Test
-    fun swipeWithKeyTimesAndEventPeriod() {
-        // Given a specific eventPeriod and a swipe with a given duration and set of keyTimes
-        subject.sendSwipe(curve = curve, duration = duration, keyTimes = keyTimes)
-
-        // then
-        recorder.assertHasValidEventTimes()
-        recorder.events.apply {
-            // down + up + #keyTimes
-            assertThat(size).isAtLeast(2 + keyTimes.size)
-
-            // Check down and up events
-            val durationMs = duration.inMilliseconds()
-            first().verify(curve, ACTION_DOWN, 0)
-            last().verify(curve, ACTION_UP, durationMs)
-
-            // Check that coordinates are the function's value at the respective timestamps
-            forEach {
-                assertThat(it.x).isEqualTo(curve(it.relativeTime).x)
-                assertThat(it.y).isEqualTo(curve(it.relativeTime).y)
-            }
-
-            // The given keyTimes must occur as event timestamps
-            // Ordering is already required on the keyTimes parameter in setUp()
-            assertThat(relativeEventTimes).containsAtLeastElementsIn(keyTimes.distinct())
-
-            // The keyTimes divide the duration in a set of intervals. Each interval should
-            // be represented by MotionEvents that divide that interval as equally as
-            // possible with as close to [eventPeriod] between each successive event as
-            // possible.
-            keyTimes.plus(durationMs).distinct().zipWithNext().forEach { (t0, t1) ->
-                val segment = moveEvents.between(t0, t1)
-                segment.splitsDurationEquallyInto(t0, t1, eventPeriod)
-            }
-        }
-    }
-}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
index ffd3ead..f7b4ead 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeLineTest.kt
@@ -25,8 +25,8 @@
 import androidx.ui.test.util.moveEvents
 import androidx.ui.test.util.splitsDurationEquallyInto
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.milliseconds
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -49,8 +49,8 @@
     )
 
     companion object {
-        private val start = PxPosition(5f, 7f)
-        private val end = PxPosition(23f, 29f)
+        private val start = Offset(5f, 7f)
+        private val end = Offset(23f, 29f)
 
         @JvmStatic
         @Parameterized.Parameters(name = "{0}")
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithDurationTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithDurationTest.kt
new file mode 100644
index 0000000..b69b16a
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithDurationTest.kt
@@ -0,0 +1,131 @@
+/*
+ * 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.test.inputdispatcher
+
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import androidx.test.filters.SmallTest
+import androidx.ui.geometry.Offset
+import androidx.ui.test.android.AndroidInputDispatcher
+import androidx.ui.test.util.MotionEventRecorder
+import androidx.ui.test.util.assertHasValidEventTimes
+import androidx.ui.test.util.verify
+import androidx.ui.unit.Duration
+import androidx.ui.unit.inMilliseconds
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
+ * function between two positions. Verifies if the generated MotionEvents for a gesture with a
+ * given duration have the expected timestamps. The timestamps should divide the duration as
+ * equally as possible with as close to [AndroidInputDispatcher.eventPeriod] between each
+ * successive event as possible.
+ */
+@SmallTest
+@RunWith(Parameterized::class)
+class SendSwipeWithDurationTest(private val config: TestConfig) {
+    data class TestConfig(
+        val duration: Duration,
+        val expectedTimestamps: List<Long>
+    )
+
+    companion object {
+        private val curve = { t: Long ->
+            Offset(t.toFloat(), (-t).toFloat())
+        }
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun createTestSet(): List<TestConfig> {
+            return listOf(
+                // With eventPeriod of 10.ms, 0 events is 0.ms and 1 event is 10.ms
+                // Even though 1.ms is closer to 0.ms than to 10.ms, split into 1 event as we
+                // must have at least 1 move event to have movement.
+                TestConfig(1.milliseconds, listOf(1)),
+                // With eventPeriod of 10.ms, 0 events is 0.ms and 1 event is 10.ms
+                // Split 7.ms in 1 event as 7.ms is closer to 10.ms than to 0.ms
+                TestConfig(7.milliseconds, listOf(7)),
+                // With eventPeriod of 10.ms, a duration of 10.ms is exactly 1 event
+                TestConfig(10.milliseconds, listOf(10)),
+                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
+                // Split 14.ms in 1 event as 14.ms is closer to 10.ms than to 20.ms
+                TestConfig(14.milliseconds, listOf(14)),
+                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
+                // 15.ms is as close to 10.ms as it is to 20.ms, in which case the larger number
+                // of events is preferred -> 2 events
+                TestConfig(15.milliseconds, listOf(8, 15)),
+                // With eventPeriod of 10.ms, 1 event is 10.ms and 2 events is 20.ms
+                // Split 19.ms in 2 events as 19.ms is closer to 20.ms than to 10.ms
+                TestConfig(19.milliseconds, listOf(10, 19)),
+                // With eventPeriod of 10.ms, 2 events is 20.ms and 3 events is 30.ms
+                // Split 24.ms in 2 events as 24.ms is closer to 20.ms than to 30.ms
+                TestConfig(24.milliseconds, listOf(12, 24)),
+                // With eventPeriod of 10.ms, 2 events is 20.ms and 3 events is 30.ms
+                // 25.ms is as close to 20.ms as it is to 30.ms, in which case the larger number
+                // of events is preferred -> 3 events
+                TestConfig(25.milliseconds, listOf(8, 17, 25)),
+                // With eventPeriod of 10.ms, 9 event is 90.ms and 10 events is 100.ms
+                // Split 97.ms in 10 events as 97.ms is closer to 100.ms than to 90.ms
+                TestConfig(97.milliseconds, listOf(10, 19, 29, 39, 49, 58, 68, 78, 87, 97))
+            )
+        }
+    }
+
+    @get:Rule
+    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
+        disableDispatchInRealTime = true
+    )
+
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::recordEvent)
+
+    @After
+    fun tearDown() {
+        recorder.disposeEvents()
+    }
+
+    @Test
+    fun swipeWithDuration() {
+        // Given a swipe with a given duration
+        subject.sendSwipe(curve = curve, duration = config.duration)
+
+        // then
+        val expectedNumberOfMoveEvents = config.expectedTimestamps.size
+        recorder.assertHasValidEventTimes()
+        recorder.events.apply {
+            // down + up + #move
+            assertThat(size).isEqualTo(2 + expectedNumberOfMoveEvents)
+
+            val durationMs = config.duration.inMilliseconds()
+            // First is down, last is up
+            first().verify(curve, ACTION_DOWN, expectedRelativeTime = 0)
+            last().verify(curve, ACTION_UP, expectedRelativeTime = durationMs)
+            // In between are all move events with the expected timestamps
+            drop(1).zip(config.expectedTimestamps).forEach { (event, expectedTimestamp) ->
+                event.verify(curve, ACTION_MOVE, expectedRelativeTime = expectedTimestamp)
+            }
+        }
+    }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesAndEventPeriodTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesAndEventPeriodTest.kt
new file mode 100644
index 0000000..3b2432c
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesAndEventPeriodTest.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.ui.test.inputdispatcher
+
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_UP
+import androidx.test.filters.SmallTest
+import androidx.ui.geometry.Offset
+import androidx.ui.test.android.AndroidInputDispatcher
+import androidx.ui.test.util.MotionEventRecorder
+import androidx.ui.test.util.assertHasValidEventTimes
+import androidx.ui.test.util.between
+import androidx.ui.test.util.moveEvents
+import androidx.ui.test.util.relativeEventTimes
+import androidx.ui.test.util.relativeTime
+import androidx.ui.test.util.splitsDurationEquallyInto
+import androidx.ui.test.util.verify
+import androidx.ui.unit.Duration
+import androidx.ui.unit.inMilliseconds
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
+ * function between two positions. Verifies if the generated MotionEvents for a gesture with a
+ * given duration and a set of keyTimes have the expected timestamps, if the event period would
+ * be different. This is not a situation that can occur in practice, but is necessary to test to
+ * ensure the calculations made by the [AndroidInputDispatcher] are correct.
+ *
+ * The timestamps of the generated events should include all keyTimes, and divide the duration
+ * between those keyTimes as equally as possible with as close to [eventPeriod] between each
+ * successive event as possible.
+ *
+ * This uses a different verification mechanism as the previous tests, because here we need to
+ * calculate the expected timestamps.
+ */
+@SmallTest
+@RunWith(Parameterized::class)
+class SendSwipeWithKeyTimesAndEventPeriodTest(private val config: TestConfig) {
+    data class TestConfig(
+        val duration: Duration,
+        val keyTimes: List<Long>,
+        val eventPeriod: Long
+    )
+
+    companion object {
+        private val curve = { t: Long ->
+            Offset(t.toFloat(), (-t).toFloat())
+        }
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun createTestSet(): List<TestConfig> {
+            return listOf(10L, 4L, 7L).flatMap { eventPeriod ->
+                // pick a prime number for duration
+                val durationMs = 101L
+                // testing all possible keyTimes between 0 and 100 takes way too long,
+                // only test several combinations keyTimes close to the middle instead
+                val firstKeyTime = (durationMs / 2) - eventPeriod
+                val lastKeyTime = (durationMs / 2) + eventPeriod
+                (firstKeyTime..lastKeyTime step eventPeriod).flatMap { keyTime1 ->
+                    (keyTime1..lastKeyTime).map { keyTime2 ->
+                        TestConfig(
+                            Duration(milliseconds = durationMs),
+                            listOf(keyTime1, keyTime2),
+                            eventPeriod
+                        )
+                    }
+                }
+            }
+        }
+    }
+
+    @get:Rule
+    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
+        disableDispatchInRealTime = true,
+        eventPeriodOverride = config.eventPeriod
+    )
+
+    private val duration get() = config.duration
+    private val keyTimes get() = config.keyTimes
+    private val eventPeriod = config.eventPeriod
+
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::recordEvent)
+
+    @Before
+    fun setUp() {
+        require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
+            "keyTimes needs to be sorted, not ${config.keyTimes}"
+        }
+    }
+
+    @After
+    fun tearDown() {
+        recorder.disposeEvents()
+    }
+
+    @Test
+    fun swipeWithKeyTimesAndEventPeriod() {
+        // Given a specific eventPeriod and a swipe with a given duration and set of keyTimes
+        subject.sendSwipe(curve = curve, duration = duration, keyTimes = keyTimes)
+
+        // then
+        recorder.assertHasValidEventTimes()
+        recorder.events.apply {
+            // down + up + #keyTimes
+            assertThat(size).isAtLeast(2 + keyTimes.size)
+
+            // Check down and up events
+            val durationMs = duration.inMilliseconds()
+            first().verify(curve, ACTION_DOWN, 0)
+            last().verify(curve, ACTION_UP, durationMs)
+
+            // Check that coordinates are the function's value at the respective timestamps
+            forEach {
+                assertThat(it.x).isEqualTo(curve(it.relativeTime).x)
+                assertThat(it.y).isEqualTo(curve(it.relativeTime).y)
+            }
+
+            // The given keyTimes must occur as event timestamps
+            // Ordering is already required on the keyTimes parameter in setUp()
+            assertThat(relativeEventTimes).containsAtLeastElementsIn(keyTimes.distinct())
+
+            // The keyTimes divide the duration in a set of intervals. Each interval should
+            // be represented by MotionEvents that divide that interval as equally as
+            // possible with as close to [eventPeriod] between each successive event as
+            // possible.
+            keyTimes.plus(durationMs).distinct().zipWithNext().forEach { (t0, t1) ->
+                val segment = moveEvents.between(t0, t1)
+                segment.splitsDurationEquallyInto(t0, t1, eventPeriod)
+            }
+        }
+    }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesTest.kt
new file mode 100644
index 0000000..13379bc
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendSwipeWithKeyTimesTest.kt
@@ -0,0 +1,128 @@
+/*
+ * 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.test.inputdispatcher
+
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import androidx.test.filters.SmallTest
+import androidx.ui.test.android.AndroidInputDispatcher
+import androidx.ui.test.util.MotionEventRecorder
+import androidx.ui.test.util.assertHasValidEventTimes
+import androidx.ui.test.util.verify
+import androidx.ui.unit.Duration
+import androidx.ui.unit.inMilliseconds
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Tests if the [AndroidInputDispatcher.sendSwipe] gesture works when specifying the gesture as a
+ * function between two positions. Verifies if the generated MotionEvents for a gesture with a
+ * given duration and a set of keyTimes have the expected timestamps. The timestamps should
+ * include all keyTimes, and divide the duration between those keyTimes as equally as possible
+ * with as close to [AndroidInputDispatcher.eventPeriod] between each successive event as possible.
+ */
+@SmallTest
+@RunWith(Parameterized::class)
+class SendSwipeWithKeyTimesTest(private val config: TestConfig) {
+    data class TestConfig(
+        val duration: Duration,
+        val keyTimes: List<Long>,
+        val expectedTimestamps: List<Long>
+    )
+
+    companion object {
+        private val curve = { t: Long ->
+            androidx.ui.geometry.Offset(t.toFloat(), (-t).toFloat())
+        }
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun createTestSet(): List<TestConfig> {
+            return listOf(
+                // 10.ms normally splits into 1 event, but here we add a keyTime that must yield
+                // an event at that time
+                TestConfig(10.milliseconds, listOf(1), listOf(1, 10)),
+                TestConfig(10.milliseconds, listOf(2), listOf(2, 10)),
+                TestConfig(10.milliseconds, listOf(3), listOf(3, 10)),
+                TestConfig(10.milliseconds, listOf(4), listOf(4, 10)),
+                TestConfig(10.milliseconds, listOf(5), listOf(5, 10)),
+                TestConfig(10.milliseconds, listOf(6), listOf(6, 10)),
+                TestConfig(10.milliseconds, listOf(7), listOf(7, 10)),
+                TestConfig(10.milliseconds, listOf(8), listOf(8, 10)),
+                TestConfig(10.milliseconds, listOf(9), listOf(9, 10)),
+                // With 2 keyTimes we expect to see both those keyTimes in the generated events
+                TestConfig(10.milliseconds, listOf(1, 9), listOf(1, 9, 10)),
+                // Same for 3 keyTimes
+                TestConfig(10.milliseconds, listOf(1, 5, 9), listOf(1, 5, 9, 10)),
+                // If two keyTimes are longer than eventPeriod apart from each other, that period
+                // must be split as usual (here: between 10 and 28)
+                TestConfig(30.milliseconds, listOf(5, 10, 28), listOf(5, 10, 19, 28, 30))
+            )
+        }
+    }
+
+    @get:Rule
+    val inputDispatcherRule: TestRule = AndroidInputDispatcher.TestRule(
+        disableDispatchInRealTime = true
+    )
+
+    private val recorder = MotionEventRecorder()
+    private val subject = AndroidInputDispatcher(recorder::recordEvent)
+
+    @Before
+    fun setUp() {
+        require(config.keyTimes.distinct() == config.keyTimes.distinct().sorted()) {
+            "keyTimes needs to be sorted, not ${config.keyTimes}"
+        }
+    }
+
+    @After
+    fun tearDown() {
+        recorder.disposeEvents()
+    }
+
+    @Test
+    fun swipeWithKeyTimes() {
+        // Given a swipe with a given duration and set of keyTimes
+        subject.sendSwipe(curve = curve, duration = config.duration, keyTimes = config.keyTimes)
+
+        // then
+        val expectedNumberOfMoveEvents = config.expectedTimestamps.size
+        recorder.assertHasValidEventTimes()
+        recorder.events.apply {
+            // down + up + #move
+            assertThat(size).isEqualTo(2 + expectedNumberOfMoveEvents)
+
+            val durationMs = config.duration.inMilliseconds()
+            // First is down, last is up
+            first().verify(curve, ACTION_DOWN, expectedRelativeTime = 0)
+            last().verify(curve, ACTION_UP, expectedRelativeTime = durationMs)
+            // In between are all move events with the expected timestamps
+            drop(1).zip(config.expectedTimestamps).forEach { (event, expectedTimestamp) ->
+                event.verify(curve, ACTION_MOVE, expectedRelativeTime = expectedTimestamp)
+            }
+        }
+    }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
index ad3bd69..95f1e95 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/inputdispatcher/SendUpTest.kt
@@ -27,7 +27,7 @@
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verifyEvent
 import androidx.ui.test.util.verifyPointer
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Rule
@@ -45,8 +45,8 @@
         private const val pointer2 = 22
 
         // positions (used with corresponding pointerId: pointerX with positionX_Y)
-        private val position1_1 = PxPosition(11f, 11f)
-        private val position2_1 = PxPosition(21f, 21f)
+        private val position1_1 = Offset(11f, 11f)
+        private val position2_1 = Offset(21f, 21f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
index 25fe407..40c0df0 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendCancelTest.kt
@@ -29,7 +29,7 @@
 import androidx.ui.test.util.MultiPointerInputRecorder
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.expectError
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -42,8 +42,8 @@
 @MediumTest
 class SendCancelTest {
     companion object {
-        private val downPosition1 = PxPosition(10f, 10f)
-        private val downPosition2 = PxPosition(20f, 20f)
+        private val downPosition1 = Offset(10f, 10f)
+        private val downPosition2 = Offset(20f, 20f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
index b4aa5d1..3ae7a1b 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendDownTest.kt
@@ -28,7 +28,7 @@
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -41,8 +41,8 @@
 @MediumTest
 class SendDownTest {
     companion object {
-        private val position1 = PxPosition(5f, 5f)
-        private val position2 = PxPosition(7f, 7f)
+        private val position1 = Offset(5f, 5f)
+        private val position2 = Offset(7f, 7f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
index 32bf84b..20894e8 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveByTest.kt
@@ -33,7 +33,7 @@
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -47,10 +47,10 @@
 @MediumTest
 class SendMoveByTest {
     companion object {
-        private val downPosition1 = PxPosition(10f, 10f)
-        private val downPosition2 = PxPosition(20f, 20f)
-        private val delta1 = PxPosition(11f, 11f)
-        private val delta2 = PxPosition(21f, 21f)
+        private val downPosition1 = Offset(10f, 10f)
+        private val downPosition2 = Offset(20f, 20f)
+        private val delta1 = Offset(11f, 11f)
+        private val delta2 = Offset(21f, 21f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveTest.kt
index 8c3fb88..4d7b032 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveTest.kt
@@ -26,7 +26,7 @@
 import androidx.ui.test.sendUp
 import androidx.ui.test.util.ClickableTestBox
 import androidx.ui.test.util.expectError
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -38,7 +38,7 @@
 @MediumTest
 class SendMoveTest() {
     companion object {
-        private val downPosition1 = PxPosition(10f, 10f)
+        private val downPosition1 = Offset(10f, 10f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
index 91baaca..c71d822 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendMoveToTest.kt
@@ -33,7 +33,7 @@
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -47,10 +47,10 @@
 @MediumTest
 class SendMoveToTest() {
     companion object {
-        private val downPosition1 = PxPosition(10f, 10f)
-        private val downPosition2 = PxPosition(20f, 20f)
-        private val moveToPosition1 = PxPosition(11f, 11f)
-        private val moveToPosition2 = PxPosition(21f, 21f)
+        private val downPosition1 = Offset(10f, 10f)
+        private val downPosition2 = Offset(20f, 20f)
+        private val moveToPosition1 = Offset(11f, 11f)
+        private val moveToPosition2 = Offset(21f, 21f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
index dc99005..38cdceb 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/partialgesturescope/SendUpTest.kt
@@ -31,7 +31,7 @@
 import androidx.ui.test.util.assertTimestampsAreIncreasing
 import androidx.ui.test.util.expectError
 import androidx.ui.test.util.verify
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -44,8 +44,8 @@
 @MediumTest
 class SendUpTest {
     companion object {
-        private val downPosition1 = PxPosition(10f, 10f)
-        private val downPosition2 = PxPosition(20f, 20f)
+        private val downPosition1 = Offset(10f, 10f)
+        private val downPosition2 = Offset(20f, 20f)
     }
 
     @get:Rule
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/MotionEvents.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/MotionEvents.kt
index 3764a54..8a47c046 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/MotionEvents.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/MotionEvents.kt
@@ -17,7 +17,7 @@
 package androidx.ui.test.util
 
 import android.view.MotionEvent
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.abs
 
@@ -54,7 +54,7 @@
 }
 
 internal fun MotionEvent.verify(
-    curve: (Long) -> PxPosition,
+    curve: (Long) -> Offset,
     expectedAction: Int,
     expectedRelativeTime: Long
 ) {
@@ -65,7 +65,7 @@
 }
 
 internal fun MotionEvent.verify(
-    expectedPosition: PxPosition,
+    expectedPosition: Offset,
     expectedAction: Int,
     expectedRelativeTime: Long
 ) {
@@ -87,7 +87,7 @@
 
 internal fun MotionEvent.verifyPointer(
     expectedPointerId: Int,
-    expectedPosition: PxPosition
+    expectedPosition: Offset
 ) {
     var index = -1
     for (i in 0 until pointerCount) {
@@ -111,7 +111,7 @@
 /**
  * Checks that the coordinates are progressing in a monotonous direction
  */
-fun List<MotionEvent>.isMonotonicBetween(start: PxPosition, end: PxPosition) {
+fun List<MotionEvent>.isMonotonicBetween(start: Offset, end: Offset) {
     map { it.x }.isMonotonicBetween(start.x, end.x, 1e-6f)
     map { it.y }.isMonotonicBetween(start.y, end.y, 1e-6f)
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
index 2837bf5..52acf8b 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/PointerInputs.kt
@@ -23,9 +23,9 @@
 import androidx.ui.core.gesture.util.VelocityTracker
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.pointerinput.PointerInputModifier
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.Duration
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
 import androidx.ui.unit.Uptime
 import com.google.common.truth.Truth.assertThat
 
@@ -125,7 +125,7 @@
     expectedTimestamp: Uptime?,
     expectedId: PointerId?,
     expectedDown: Boolean,
-    expectedPosition: PxPosition
+    expectedPosition: Offset
 ) {
     if (expectedTimestamp != null) {
         assertThat(timestamp).isEqualTo(expectedTimestamp)
@@ -140,7 +140,7 @@
 /**
  * Checks that the coordinates are progressing in a monotonous direction
  */
-fun List<DataPoint>.isMonotonicBetween(start: PxPosition, end: PxPosition) {
+fun List<DataPoint>.isMonotonicBetween(start: Offset, end: Offset) {
     map { it.x }.isMonotonicBetween(start.x, end.x, 1e-3f)
     map { it.y }.isMonotonicBetween(start.y, end.y, 1e-3f)
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Truth.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Truth.kt
index ec5d32d..1cc2dea 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Truth.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Truth.kt
@@ -16,7 +16,8 @@
 
 package androidx.ui.test.util
 
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
+import com.google.common.collect.Ordering
 import com.google.common.truth.FloatSubject
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.sign
@@ -30,10 +31,10 @@
 }
 
 /**
- * Verifies that the [PxPosition] is equal to the given position with some tolerance. The default
+ * Verifies that the [Offset] is equal to the given position with some tolerance. The default
  * tolerance is 0.001.
  */
-fun PxPosition.isAlmostEqualTo(position: PxPosition, tolerance: Float = 1e-3f) {
+fun Offset.isAlmostEqualTo(position: Offset, tolerance: Float = 1e-3f) {
     assertThat(x).isAlmostEqualTo(position.x, tolerance)
     assertThat(y).isAlmostEqualTo(position.y, tolerance)
 }
@@ -55,6 +56,13 @@
     }
 }
 
+fun List<Float>.assertSame(tolerance: Float = 0f) {
+    if (size <= 1) {
+        return
+    }
+    assertThat(min()!!).isWithin(2 * tolerance).of(max()!!)
+}
+
 /**
  * Checks that the float value is between [a] and [b], allowing a [tolerance] on either side.
  * The order of [a] and [b] doesn't matter, the float value must be _between_ them. The default
@@ -69,3 +77,11 @@
         isAtMost(a + tolerance)
     }
 }
+
+fun <E : Comparable<E>> List<E>.assertIncreasing() {
+    assertThat(this).isInOrder(Ordering.natural<E>())
+}
+
+fun <E : Comparable<E>> List<E>.assertDecreasing() {
+    assertThat(this).isInOrder(Ordering.natural<E>().reverse<E>())
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt b/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
index 1f1ceb8..b3a4257 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
@@ -20,7 +20,7 @@
 import androidx.ui.semantics.AccessibilityAction
 import androidx.ui.semantics.SemanticsActions
 import androidx.ui.semantics.SemanticsPropertyKey
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * Performs a click action on the given component.
@@ -66,7 +66,7 @@
             "No Layout Node found!"
         )
 
-    val position = layoutNode.coordinates.localToGlobal(PxPosition(0.0f, 0.0f))
+    val position = layoutNode.coordinates.localToGlobal(Offset(0.0f, 0.0f))
 
     runOnUiThread {
         scrollableSemanticsNode.config[SemanticsActions.ScrollTo].action(
@@ -113,7 +113,7 @@
  *
  * Example usage:
  * ```
- * val position = PxPosition(10.px, 10.px)
+ * val position = Offset(10f, 10f)
  * findByTag("myWidget")
  *    .doPartialGesture { sendDown(position) }
  *    .assertHasClickAction()
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
index 84a8f75..6cf6c0e 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
@@ -24,10 +24,7 @@
 import androidx.ui.semantics.AccessibilityRangeInfo
 import androidx.ui.semantics.SemanticsProperties
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.PxSize
 import androidx.ui.unit.height
-import androidx.ui.unit.px
 import androidx.ui.unit.width
 
 /**
@@ -326,8 +323,10 @@
 
     val displayMetrics = (componentNode.owner as AndroidOwner).view.resources.displayMetrics
     val screenBounds = PxBounds(
-        PxPosition.Origin,
-        PxSize(displayMetrics.widthPixels.px, displayMetrics.heightPixels.px)
+        left = 0f,
+        top = 0f,
+        right = displayMetrics.widthPixels.toFloat(),
+        bottom = displayMetrics.heightPixels.toFloat()
     )
 
     return nodeBounds.top >= screenBounds.top &&
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
index 8d65ad2..2cd3a56 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
@@ -129,10 +129,10 @@
 fun Path.contains(offset: Offset): Boolean {
     val path = android.graphics.Path()
     path.addRect(
-        offset.dx - 0.01f,
-        offset.dy - 0.01f,
-        offset.dx + 0.01f,
-        offset.dy + 0.01f,
+        offset.x - 0.01f,
+        offset.y - 0.01f,
+        offset.x + 0.01f,
+        offset.y + 0.01f,
         android.graphics.Path.Direction.CW
     )
     if (path.op(asAndroidPath(), android.graphics.Path.Op.INTERSECT)) {
@@ -281,14 +281,14 @@
     val centerY = shapeSizeY / 2f
     val d = delta
     val x = when {
-        offset.dx > centerX -> offset.dx - d
-        offset.dx < centerX -> offset.dx + d
-        else -> offset.dx
+        offset.x > centerX -> offset.x - d
+        offset.x < centerX -> offset.x + d
+        else -> offset.x
     }
     val y = when {
-        offset.dy > centerY -> offset.dy - d
-        offset.dy < centerY -> offset.dy + d
-        else -> offset.dy
+        offset.y > centerY -> offset.y - d
+        offset.y < centerY -> offset.y + d
+        else -> offset.y
     }
     return Offset(x, y)
 }
@@ -303,14 +303,14 @@
     val centerY = shapeSizeY / 2f
     val d = delta
     val x = when {
-        offset.dx > centerX -> offset.dx + d
-        offset.dx < centerX -> offset.dx - d
-        else -> offset.dx
+        offset.x > centerX -> offset.x + d
+        offset.x < centerX -> offset.x - d
+        else -> offset.x
     }
     val y = when {
-        offset.dy > centerY -> offset.dy + d
-        offset.dy < centerY -> offset.dy - d
-        else -> offset.dy
+        offset.y > centerY -> offset.y + d
+        offset.y < centerY -> offset.y - d
+        else -> offset.y
     }
     return Offset(x, y)
 }
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt b/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt
index 152f7d9..e62f3f8 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/GestureScope.kt
@@ -22,7 +22,8 @@
 import androidx.ui.unit.Duration
 import androidx.ui.unit.IntPxSize
 import androidx.ui.unit.PxBounds
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.milliseconds
 import androidx.ui.util.lerp
@@ -80,9 +81,9 @@
  * Returns the center of the component we're interacting with, in the component's local
  * coordinate system, where (0.px, 0.px) is the top left corner of the component.
  */
-val BaseGestureScope.center: PxPosition
+val BaseGestureScope.center: Offset
     get() {
-        return PxPosition(size.width / 2, size.height / 2)
+        return Offset(size.width.value / 2f, size.height.value / 2f)
     }
 
 /**
@@ -96,9 +97,9 @@
  *
  * @param position A position in local coordinates
  */
-fun BaseGestureScope.localToGlobal(position: PxPosition): PxPosition {
+fun BaseGestureScope.localToGlobal(position: Offset): Offset {
     val bounds = globalBounds
-    return position + PxPosition(bounds.left, bounds.top)
+    return position + Offset(bounds.left, bounds.top)
 }
 
 /**
@@ -130,7 +131,7 @@
  * @param position The position where to click, in the component's local coordinate system. If
  * omitted, the center position will be used.
  */
-fun GestureScope.sendClick(position: PxPosition = center) {
+fun GestureScope.sendClick(position: Offset = center) {
     inputDispatcher.sendClick(localToGlobal(position))
 }
 
@@ -145,7 +146,7 @@
  * @param position The position of the long click, in the component's local coordinate system. If
  * omitted, the center position will be used.
  */
-fun GestureScope.sendLongClick(position: PxPosition = center) {
+fun GestureScope.sendLongClick(position: Offset = center) {
     // Keep down for 100ms more than needed, to allow the long press logic to trigger
     sendSwipe(position, position, LongPressTimeout + 100.milliseconds)
 }
@@ -160,7 +161,7 @@
  * @param position The position of the double click, in the component's local coordinate system.
  * If omitted, the center position will be used.
  */
-fun GestureScope.sendDoubleClick(position: PxPosition = center) {
+fun GestureScope.sendDoubleClick(position: Offset = center) {
     val globalPosition = localToGlobal(position)
     inputDispatcher.sendClick(globalPosition)
     inputDispatcher.delay(doubleClickDelay)
@@ -180,8 +181,8 @@
  * @param duration The duration of the gesture
  */
 fun GestureScope.sendSwipe(
-    start: PxPosition,
-    end: PxPosition,
+    start: Offset,
+    end: Offset,
     duration: Duration = 200.milliseconds
 ) {
     val globalStart = localToGlobal(start)
@@ -192,7 +193,7 @@
 /**
  * Performs a pinch gesture on the associated component.
  *
- * For each pair of start and end [PxPosition]s, the motion events are linearly interpolated. The
+ * For each pair of start and end [Offset]s, the motion events are linearly interpolated. The
  * coordinates are in the component's local coordinate system where (0.px, 0.px) is the top left
  * corner of the component. The default duration is 400 milliseconds.
  *
@@ -203,10 +204,10 @@
  * @param duration the duration of the gesture
  */
 fun GestureScope.sendPinch(
-    start0: PxPosition,
-    end0: PxPosition,
-    start1: PxPosition,
-    end1: PxPosition,
+    start0: Offset,
+    end0: Offset,
+    start1: Offset,
+    end1: Offset,
     duration: Duration = 400.milliseconds
 ) {
     val globalStart0 = localToGlobal(start0)
@@ -216,9 +217,9 @@
     val durationFloat = duration.inMilliseconds().toFloat()
 
     inputDispatcher.sendSwipes(
-        listOf<(Long) -> PxPosition>(
-            { androidx.ui.unit.lerp(globalStart0, globalEnd0, it / durationFloat) },
-            { androidx.ui.unit.lerp(globalStart1, globalEnd1, it / durationFloat) }
+        listOf<(Long) -> Offset>(
+            { lerp(globalStart0, globalEnd0, it / durationFloat) },
+            { lerp(globalStart1, globalEnd1, it / durationFloat) }
         ),
         duration
     )
@@ -243,8 +244,8 @@
  * are generated, which happens with a duration of 25ms or more.
  */
 fun GestureScope.sendSwipeWithVelocity(
-    start: PxPosition,
-    end: PxPosition,
+    start: Offset,
+    end: Offset,
     @FloatRange(from = 0.0) endVelocity: Float,
     duration: Duration = 200.milliseconds
 ) {
@@ -280,7 +281,7 @@
     val fx = createFunctionForVelocity(durationMs, globalStart.x, globalEnd.x, vx)
     val fy = createFunctionForVelocity(durationMs, globalStart.y, globalEnd.y, vy)
 
-    inputDispatcher.sendSwipe({ t -> PxPosition(fx(t), fy(t)) }, duration)
+    inputDispatcher.sendSwipe({ t -> Offset(fx(t), fy(t)) }, duration)
 }
 
 /**
@@ -293,8 +294,8 @@
     val x = center.x
     val y0 = (size.height * (1 - edgeFuzzFactor)).value.toFloat()
     val y1 = 0.0f
-    val start = PxPosition(x, y0)
-    val end = PxPosition(x, y1)
+    val start = Offset(x, y0)
+    val end = Offset(x, y1)
     sendSwipe(start, end, 200.milliseconds)
 }
 
@@ -308,8 +309,8 @@
     val x = center.x
     val y0 = (size.height * edgeFuzzFactor).value.toFloat()
     val y1 = size.height.value.toFloat()
-    val start = PxPosition(x, y0)
-    val end = PxPosition(x, y1)
+    val start = Offset(x, y0)
+    val end = Offset(x, y1)
     sendSwipe(start, end, 200.milliseconds)
 }
 
@@ -323,8 +324,8 @@
     val x0 = (size.width * (1 - edgeFuzzFactor)).value.toFloat()
     val x1 = 0.0f
     val y = center.y
-    val start = PxPosition(x0, y)
-    val end = PxPosition(x1, y)
+    val start = Offset(x0, y)
+    val end = Offset(x1, y)
     sendSwipe(start, end, 200.milliseconds)
 }
 
@@ -338,8 +339,8 @@
     val x0 = (size.width * edgeFuzzFactor).value.toFloat()
     val x1 = size.width.value.toFloat()
     val y = center.y
-    val start = PxPosition(x0, y)
-    val end = PxPosition(x1, y)
+    val start = Offset(x0, y)
+    val end = Offset(x1, y)
     sendSwipe(start, end, 200.milliseconds)
 }
 
@@ -413,7 +414,7 @@
  *
  * Example usage:
  * ```
- * val position = PxPosition(10.px, 10.px)
+ * val position = Offset(10.px, 10.px)
  * findByTag("myWidget")
  *    .doPartialGesture { sendDown(position) }
  *    .assertIsDisplayed()
@@ -459,7 +460,7 @@
  * @param pointerId The id of the pointer, can be any number not yet in use by another pointer
  * @param position The position of the down event, in the component's local coordinate system
  */
-fun PartialGestureScope.sendDown(pointerId: Int, position: PxPosition) {
+fun PartialGestureScope.sendDown(pointerId: Int, position: Offset) {
     val globalPosition = localToGlobal(position)
     inputDispatcher.sendDown(pointerId, globalPosition)
 }
@@ -475,7 +476,7 @@
  *
  * @param position The position of the down event, in the component's local coordinate system
  */
-fun PartialGestureScope.sendDown(position: PxPosition) {
+fun PartialGestureScope.sendDown(position: Offset) {
     sendDown(0, position)
 }
 
@@ -489,7 +490,7 @@
  * @param pointerId The id of the pointer to move, as supplied in [sendDown]
  * @param position The new position of the pointer, in the component's local coordinate system
  */
-fun PartialGestureScope.sendMoveTo(pointerId: Int, position: PxPosition) {
+fun PartialGestureScope.sendMoveTo(pointerId: Int, position: Offset) {
     movePointerTo(pointerId, position)
     sendMove()
 }
@@ -503,7 +504,7 @@
  *
  * @param position The new position of the pointer, in the component's local coordinate system
  */
-fun PartialGestureScope.sendMoveTo(position: PxPosition) {
+fun PartialGestureScope.sendMoveTo(position: Offset) {
     sendMoveTo(0, position)
 }
 
@@ -518,7 +519,7 @@
  * @param pointerId The id of the pointer to move, as supplied in [sendDown]
  * @param position The new position of the pointer, in the component's local coordinate system
  */
-fun PartialGestureScope.movePointerTo(pointerId: Int, position: PxPosition) {
+fun PartialGestureScope.movePointerTo(pointerId: Int, position: Offset) {
     val globalPosition = localToGlobal(position)
     inputDispatcher.movePointer(pointerId, globalPosition)
 }
@@ -531,10 +532,10 @@
  *
  * @param pointerId The id of the pointer to move, as supplied in [sendDown]
  * @param delta The position for this move event, relative to the last sent position of the
- * pointer. For example, `delta = PxPosition(10.px, -10.px) will add 10.px to the pointer's last
+ * pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last
  * x-position, and subtract 10.px from the pointer's last y-position.
  */
-fun PartialGestureScope.sendMoveBy(pointerId: Int, delta: PxPosition) {
+fun PartialGestureScope.sendMoveBy(pointerId: Int, delta: Offset) {
     movePointerBy(pointerId, delta)
     sendMove()
 }
@@ -546,10 +547,10 @@
  * If the pointer is not yet down, an [IllegalArgumentException] will be thrown.
  *
  * @param delta The position for this move event, relative to the last sent position of the
- * pointer. For example, `delta = PxPosition(10.px, -10.px) will add 10.px to the pointer's last
+ * pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last
  * x-position, and subtract 10.px from the pointer's last y-position.
  */
-fun PartialGestureScope.sendMoveBy(delta: PxPosition) {
+fun PartialGestureScope.sendMoveBy(delta: Offset) {
     sendMoveBy(0, delta)
 }
 
@@ -561,13 +562,13 @@
  *
  * @param pointerId The id of the pointer to move, as supplied in [sendDown]
  * @param delta The position for this move event, relative to the last sent position of the
- * pointer. For example, `delta = PxPosition(10.px, -10.px) will add 10.px to the pointer's last
+ * pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last
  * x-position, and subtract 10.px from the pointer's last y-position.
  */
-fun PartialGestureScope.movePointerBy(pointerId: Int, delta: PxPosition) {
+fun PartialGestureScope.movePointerBy(pointerId: Int, delta: Offset) {
     // Ignore currentPosition of null here, let movePointer generate the error
     val globalPosition =
-        (inputDispatcher.getCurrentPosition(pointerId) ?: PxPosition.Origin) + delta
+        (inputDispatcher.getCurrentPosition(pointerId) ?: Offset.Zero) + delta
     inputDispatcher.movePointer(pointerId, globalPosition)
 }
 
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt b/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt
index 9b7606c..b0ce05a 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/InputDispatcher.kt
@@ -22,7 +22,8 @@
 import androidx.ui.test.android.AndroidInputDispatcher
 import androidx.ui.test.android.AndroidOwnerRegistry
 import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.lerp
 import java.util.WeakHashMap
@@ -86,7 +87,7 @@
      *
      * @param position The coordinate of the click
      */
-    fun sendClick(position: PxPosition) {
+    fun sendClick(position: Offset) {
         sendDown(0, position)
         sendMove()
         sendUp(0)
@@ -100,7 +101,7 @@
      * @param end The end position of the gesture
      * @param duration The duration of the gesture
      */
-    fun sendSwipe(start: PxPosition, end: PxPosition, duration: Duration) {
+    fun sendSwipe(start: Offset, end: Offset, duration: Duration) {
         val durationFloat = duration.inMilliseconds().toFloat()
         sendSwipe(
             curve = { lerp(start, end, it / durationFloat) },
@@ -120,7 +121,7 @@
      * be sampled
      */
     fun sendSwipe(
-        curve: (Long) -> PxPosition,
+        curve: (Long) -> Offset,
         duration: Duration,
         keyTimes: List<Long> = emptyList()
     ) {
@@ -140,7 +141,7 @@
      * be sampled
      */
     fun sendSwipes(
-        curves: List<(Long) -> PxPosition>,
+        curves: List<(Long) -> Offset>,
         duration: Duration,
         keyTimes: List<Long> = emptyList()
     )
@@ -167,7 +168,7 @@
      * @return The current position of the pointer with the given [pointerId], or `null` if the
      * pointer is not currently in use
      */
-    fun getCurrentPosition(pointerId: Int): PxPosition?
+    fun getCurrentPosition(pointerId: Int): Offset?
 
     /**
      * Sends a down event at [position] for the pointer with the given [pointerId], starting a
@@ -202,7 +203,7 @@
      * @see sendUp
      * @see sendCancel
      */
-    fun sendDown(pointerId: Int, position: PxPosition)
+    fun sendDown(pointerId: Int, position: Offset)
 
     /**
      * Updates the position of the pointer with the given [pointerId] to the given [position],
@@ -221,7 +222,7 @@
      * @see sendUp
      * @see sendCancel
      */
-    fun movePointer(pointerId: Int, position: PxPosition)
+    fun movePointer(pointerId: Int, position: Offset)
 
     /**
      * Sends a move event 10 milliseconds after the previous injected event of this gesture,
@@ -288,8 +289,8 @@
     val partialGesture: PartialGesture?
 )
 
-internal class PartialGesture(val downTime: Long, startPosition: PxPosition, pointerId: Int) {
+internal class PartialGesture(val downTime: Long, startPosition: Offset, pointerId: Int) {
     var lastEventTime: Long = downTime
-    val lastPositions = SparseArrayCompat<PxPosition>().apply { put(pointerId, startPosition) }
+    val lastPositions = SparseArrayCompat<Offset>().apply { put(pointerId, startPosition) }
     var hasPointerUpdates: Boolean = false
 }
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/TestAnimationClock.kt b/ui/ui-test/src/main/java/androidx/ui/test/TestAnimationClock.kt
index d8fdb44..ab8373e 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/TestAnimationClock.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/TestAnimationClock.kt
@@ -121,6 +121,7 @@
         return AnimationClockStatement(base)
     }
 
+    @OptIn(androidx.animation.InternalAnimationApi::class)
     private inner class AnimationClockStatement(private val base: Statement) : Statement() {
         override fun evaluate() {
             val oldFactory = rootAnimationClockFactory
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
index 30fa720..c6d0966 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestRule.kt
@@ -24,7 +24,6 @@
 import androidx.activity.ComponentActivity
 import androidx.compose.Composable
 import androidx.compose.Recomposer
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.animation.transitionsEnabled
 import androidx.ui.core.setContent
 import androidx.ui.input.textInputServiceFactory
@@ -58,7 +57,12 @@
     // already there. This is issue in case the user already set some compose content and decides
     // to set it again via our API. In such case we won't be able to dispose the old composition.
     // Other option would be to provide a smaller interface that does not expose these methods.
-    return AndroidComposeTestRule(ActivityTestRule(T::class.java), recomposer, disableTransitions)
+    @Suppress("DEPRECATION")
+    return AndroidComposeTestRule(
+        androidx.test.rule.ActivityTestRule(T::class.java),
+        recomposer,
+        disableTransitions
+    )
 }
 
 /**
@@ -70,7 +74,7 @@
 class AndroidComposeTestRule<T : ComponentActivity>(
     // TODO(b/153623653): Remove activityTestRule from arguments when AndroidComposeTestRule can
     //  work with any kind of Activity launcher.
-    val activityTestRule: ActivityTestRule<T>,
+    @Suppress("DEPRECATION") val activityTestRule: androidx.test.rule.ActivityTestRule<T>,
     val recomposer: Recomposer? = null,
     private val disableTransitions: Boolean = false
 ) : ComposeTestRule {
@@ -143,12 +147,13 @@
         private val base: Statement
     ) : Statement() {
         override fun evaluate() {
-            val oldTextInputFactory = textInputServiceFactory
+            val oldTextInputFactory = @Suppress("DEPRECATION_ERROR")(textInputServiceFactory)
             beforeEvaluate()
             try {
                 base.evaluate()
             } finally {
                 afterEvaluate()
+                @Suppress("DEPRECATION_ERROR")
                 textInputServiceFactory = oldTextInputFactory
             }
         }
@@ -158,6 +163,7 @@
             AndroidOwnerRegistry.setupRegistry()
             FirstDrawRegistry.setupRegistry()
             registerComposeWithEspresso()
+            @Suppress("DEPRECATION_ERROR")
             textInputServiceFactory = {
                 TextInputServiceForTests(it)
             }
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
index 42c915a..59de9f6 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
@@ -30,7 +30,7 @@
 import androidx.ui.test.InputDispatcherState
 import androidx.ui.test.PartialGesture
 import androidx.ui.unit.Duration
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.inMilliseconds
 import androidx.ui.unit.milliseconds
 import androidx.ui.util.lerp
@@ -118,11 +118,11 @@
         sleepUntil(nextDownTime)
     }
 
-    override fun getCurrentPosition(pointerId: Int): PxPosition? {
+    override fun getCurrentPosition(pointerId: Int): Offset? {
         return partialGesture?.lastPositions?.get(pointerId)
     }
 
-    override fun sendDown(pointerId: Int, position: PxPosition) {
+    override fun sendDown(pointerId: Int, position: Offset) {
         var gesture = partialGesture
 
         // Check if this pointer is not already down
@@ -149,7 +149,7 @@
     }
 
     // Move 1 pointer and don't send a move event
-    override fun movePointer(pointerId: Int, position: PxPosition) {
+    override fun movePointer(pointerId: Int, position: Offset) {
         val gesture = partialGesture
 
         // Check if this pointer is in the gesture
@@ -258,7 +258,7 @@
     }
 
     override fun sendSwipes(
-        curves: List<(Long) -> PxPosition>,
+        curves: List<(Long) -> Offset>,
         duration: Duration,
         keyTimes: List<Long>
     ) {
@@ -314,7 +314,7 @@
      * @param tN The end time of this segment of the swipe, in milliseconds relative to downTime
      */
     private fun sendPartialSwipes(
-        fs: List<(Long) -> PxPosition>,
+        fs: List<(Long) -> Offset>,
         t0: Long,
         tN: Long
     ) {
@@ -343,7 +343,7 @@
         eventTime: Long,
         action: Int,
         actionIndex: Int,
-        coordinates: List<PxPosition>,
+        coordinates: List<Offset>,
         pointerIds: List<Int>
     ) {
         sleepUntil(eventTime)
diff --git a/ui/ui-text-core/api/0.1.0-dev14.txt b/ui/ui-text-core/api/0.1.0-dev14.txt
index 555966b1..981c016 100644
--- a/ui/ui-text-core/api/0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/0.1.0-dev14.txt
@@ -70,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -175,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -265,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -331,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -388,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -570,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -677,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -842,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/api/current.txt b/ui/ui-text-core/api/current.txt
index 555966b1..981c016 100644
--- a/ui/ui-text-core/api/current.txt
+++ b/ui/ui-text-core/api/current.txt
@@ -70,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -175,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -265,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -331,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -388,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -570,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -677,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -842,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
index 555966b1..981c016 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
@@ -70,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -175,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -265,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -331,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -388,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -570,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -677,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -842,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/api/public_plus_experimental_current.txt b/ui/ui-text-core/api/public_plus_experimental_current.txt
index 555966b1..981c016 100644
--- a/ui/ui-text-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_current.txt
@@ -70,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -175,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -265,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -331,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -388,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -570,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -677,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -842,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev14.txt b/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
index 5ec6c02..981c016 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
@@ -45,11 +45,6 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class EditProcessor {
-    method public androidx.ui.input.EditorValue onEditCommands(java.util.List<? extends androidx.ui.input.EditOperation> ops);
-    method public void onNewState(androidx.ui.input.EditorValue model, androidx.ui.input.TextInputService? textInputService, int token);
-  }
-
   public final class EditingBuffer {
     ctor public EditingBuffer(String initialText, androidx.ui.text.TextRange initialSelection);
     field public static final int NOWHERE = -1; // 0xffffffff
@@ -75,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -180,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -270,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -336,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -393,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -528,30 +531,6 @@
     method public static String toUpperCase(String, androidx.ui.text.LocaleList localeList);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TextDelegate {
-    ctor public TextDelegate(androidx.ui.text.AnnotatedString text, androidx.ui.text.TextStyle style, int maxLines, boolean softWrap, androidx.ui.text.style.TextOverflow overflow, androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader, java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>> placeholders);
-    method public androidx.ui.unit.Density getDensity();
-    method public int getMaxIntrinsicWidth();
-    method public int getMaxLines();
-    method public int getMinIntrinsicWidth();
-    method public androidx.ui.text.style.TextOverflow getOverflow();
-    method public java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>> getPlaceholders();
-    method public androidx.ui.text.font.Font.ResourceLoader getResourceLoader();
-    method public boolean getSoftWrap();
-    method public androidx.ui.text.TextStyle getStyle();
-    method public androidx.ui.text.AnnotatedString getText();
-    method public androidx.ui.text.TextLayoutResult layout(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.text.TextLayoutResult? prevResult = null);
-    method public void layoutIntrinsics(androidx.ui.core.LayoutDirection layoutDirection);
-    property public final int maxIntrinsicWidth;
-    property public final int minIntrinsicWidth;
-    field public static final androidx.ui.text.TextDelegate.Companion! Companion;
-  }
-
-  public static final class TextDelegate.Companion {
-    method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    method public void paintBackground(int start, int end, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-  }
-
   public final class TextLayoutHelperKt {
   }
 
@@ -599,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -706,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -871,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/api/restricted_current.txt b/ui/ui-text-core/api/restricted_current.txt
index 5ec6c02..981c016 100644
--- a/ui/ui-text-core/api/restricted_current.txt
+++ b/ui/ui-text-core/api/restricted_current.txt
@@ -45,11 +45,6 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class EditProcessor {
-    method public androidx.ui.input.EditorValue onEditCommands(java.util.List<? extends androidx.ui.input.EditOperation> ops);
-    method public void onNewState(androidx.ui.input.EditorValue model, androidx.ui.input.TextInputService? textInputService, int token);
-  }
-
   public final class EditingBuffer {
     ctor public EditingBuffer(String initialText, androidx.ui.text.TextRange initialSelection);
     field public static final int NOWHERE = -1; // 0xffffffff
@@ -75,6 +70,9 @@
     method public void process(androidx.ui.input.EditingBuffer buffer);
   }
 
+  public final class GapBufferKt {
+  }
+
   public enum ImeAction {
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
@@ -180,6 +178,8 @@
   }
 
   public final class TextInputServiceKt {
+    method @Deprecated public static kotlin.jvm.functions.Function1<androidx.ui.input.PlatformTextInputService,androidx.ui.input.TextInputService> getTextInputServiceFactory();
+    method @Deprecated public static void setTextInputServiceFactory(kotlin.jvm.functions.Function1<? super androidx.ui.input.PlatformTextInputService,? extends androidx.ui.input.TextInputService> p);
     field public static final int INVALID_SESSION = -1; // 0xffffffff
     field public static final int NO_SESSION = 0; // 0x0
   }
@@ -270,6 +270,9 @@
     method public static inline <R> R withStyle(androidx.ui.text.AnnotatedString.Builder, androidx.ui.text.ParagraphStyle style, kotlin.jvm.functions.Function1<? super androidx.ui.text.AnnotatedString.Builder,? extends R> block);
   }
 
+  public final class JvmAnnotatedStringKt {
+  }
+
   @androidx.compose.Immutable public final class Locale {
     ctor public Locale(String languageTag);
     method public String getLanguage();
@@ -336,7 +339,7 @@
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -393,7 +396,7 @@
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -528,30 +531,6 @@
     method public static String toUpperCase(String, androidx.ui.text.LocaleList localeList);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class TextDelegate {
-    ctor public TextDelegate(androidx.ui.text.AnnotatedString text, androidx.ui.text.TextStyle style, int maxLines, boolean softWrap, androidx.ui.text.style.TextOverflow overflow, androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader, java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>> placeholders);
-    method public androidx.ui.unit.Density getDensity();
-    method public int getMaxIntrinsicWidth();
-    method public int getMaxLines();
-    method public int getMinIntrinsicWidth();
-    method public androidx.ui.text.style.TextOverflow getOverflow();
-    method public java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>> getPlaceholders();
-    method public androidx.ui.text.font.Font.ResourceLoader getResourceLoader();
-    method public boolean getSoftWrap();
-    method public androidx.ui.text.TextStyle getStyle();
-    method public androidx.ui.text.AnnotatedString getText();
-    method public androidx.ui.text.TextLayoutResult layout(androidx.ui.core.Constraints constraints, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.text.TextLayoutResult? prevResult = null);
-    method public void layoutIntrinsics(androidx.ui.core.LayoutDirection layoutDirection);
-    property public final int maxIntrinsicWidth;
-    property public final int minIntrinsicWidth;
-    field public static final androidx.ui.text.TextDelegate.Companion! Companion;
-  }
-
-  public static final class TextDelegate.Companion {
-    method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    method public void paintBackground(int start, int end, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-  }
-
   public final class TextLayoutHelperKt {
   }
 
@@ -599,7 +578,7 @@
     method public int getLineForOffset(int offset);
     method public int getLineStart(int lineIndex);
     method public float getLineTop(int lineIndex);
-    method public int getOffsetForPosition(androidx.ui.unit.PxPosition position);
+    method public int getOffsetForPosition(androidx.ui.geometry.Offset position);
     method public androidx.ui.text.style.TextDirection getParagraphDirection(int offset);
     method public androidx.ui.graphics.Path getPathForRange(int start, int end);
     method public java.util.List<androidx.ui.geometry.Rect> getPlaceholderRects();
@@ -706,10 +685,6 @@
     property public abstract androidx.ui.text.font.FontFamily fontFamily;
   }
 
-  public final class TypefaceKt {
-    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
-  }
-
 }
 
 package androidx.ui.text.font {
@@ -871,12 +846,25 @@
   public final class AndroidParagraphHelperKt {
   }
 
+  public final class AndroidParagraphIntrinsicsKt {
+  }
+
   public final class AndroidParagraphKt {
   }
 
+  public final class AndroidPlatformLocaleKt {
+  }
+
+  public final class AndroidStringDelegateKt {
+  }
+
   public final class PlatformLocaleKt {
   }
 
+  public final class TypefaceAdapterKt {
+    method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
+  }
+
 }
 
 package androidx.ui.text.style {
diff --git a/ui/ui-text-core/build.gradle b/ui/ui-text-core/build.gradle
index 9cae4b9..957a005 100644
--- a/ui/ui-text-core/build.gradle
+++ b/ui/ui-text-core/build.gradle
@@ -25,45 +25,60 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXUiPlugin")
-    id("org.jetbrains.kotlin.android")
+    id("kotlin-multiplatform")
 }
 
-dependencies {
-    implementation(KOTLIN_STDLIB)
+kotlin {
+    android()
+    sourceSets {
+        commonMain.dependencies {
+            implementation(KOTLIN_STDLIB_COMMON)
 
-    // TODO: Non-Kotlin dependency, move to Android-specific code
-    implementation "androidx.collection:collection:1.1.0"
-    // TODO: Non-Kotlin dependency, move to Android-specific code
-    implementation "androidx.core:core:1.0.2"
+            api project(":ui:ui-unit")
+            api project(":ui:ui-graphics")
 
-    implementation project(":compose:compose-runtime")
-    implementation project(":ui:ui-util")
-    implementation project(":ui:ui-text-android")
-    api project(":ui:ui-unit")
-    api project(":ui:ui-graphics")
+            implementation project(":compose:compose-runtime")
+            implementation project(":ui:ui-util")
+        }
 
-    testImplementation project(":ui:ui-test-font")
-    testImplementation(ANDROIDX_TEST_RULES)
-    testImplementation(ANDROIDX_TEST_RUNNER)
-    testImplementation(JUNIT)
-    testImplementation(MOCKITO_CORE)
-    testImplementation(TRUTH)
-    testImplementation(KOTLIN_REFLECT)
-    testImplementation MOCKITO_KOTLIN, {
-        exclude group: 'org.mockito' // to keep control on the mockito version
-    }
+        jvmMain.dependencies {
+            implementation(KOTLIN_STDLIB)
+        }
 
+        androidMain.dependencies {
+            api "androidx.annotation:annotation:1.1.0"
+            implementation "androidx.collection:collection:1.1.0"
+            implementation "androidx.core:core:1.0.2"
+            implementation project(":ui:ui-text-android")
+        }
 
-    androidTestImplementation project(":ui:ui-test-font")
-    androidTestImplementation(ANDROIDX_TEST_RULES)
-    androidTestImplementation(ANDROIDX_TEST_RUNNER)
-    androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
-    androidTestImplementation(ESPRESSO_CORE)
-    androidTestImplementation(JUNIT)
-    androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
-    androidTestImplementation(TRUTH)
-    androidTestImplementation MOCKITO_KOTLIN, {
-        exclude group: 'org.mockito' // to keep control on the mockito version
+        androidTest.dependencies {
+            implementation project(":ui:ui-test-font")
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(JUNIT)
+            implementation(MOCKITO_CORE)
+            implementation(TRUTH)
+            implementation(KOTLIN_REFLECT)
+            implementation MOCKITO_KOTLIN, {
+                exclude group: 'org.mockito' // to keep control on the mockito version
+            }
+        }
+
+        androidAndroidTest.dependencies {
+            implementation project(":ui:ui-test-font")
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(ESPRESSO_CORE)
+            implementation(JUNIT)
+            implementation project(":ui:ui-test")
+            implementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+            implementation(MOCKITO_CORE, libs.exclude_bytebuddy)
+            implementation(TRUTH)
+            implementation MOCKITO_KOTLIN, {
+                exclude group: 'org.mockito' // to keep control on the mockito version
+            }
+        }
     }
 }
 
@@ -79,5 +94,10 @@
 tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
         useIR = true
+        freeCompilerArgs += ["-XXLanguage:+InlineClasses"]
     }
 }
+
+android.buildTypes.all {
+    testCoverageEnabled = false
+}
diff --git a/ui/ui-text-core/src/androidTest/AndroidManifest.xml b/ui/ui-text-core/src/androidAndroidTest/AndroidManifest.xml
similarity index 100%
rename from ui/ui-text-core/src/androidTest/AndroidManifest.xml
rename to ui/ui-text-core/src/androidAndroidTest/AndroidManifest.xml
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/input/BackspaceKeyEditOpTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/input/BackspaceKeyEditOpTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/input/BackspaceKeyEditOpTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/input/BackspaceKeyEditOpTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/input/MoveCursorEditOpTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/input/MoveCursorEditOpTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/input/MoveCursorEditOpTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/input/MoveCursorEditOpTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/FontTestData.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/FontTestData.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/FontTestData.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/FontTestData.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/LocaleListTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/LocaleListTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/LocaleListTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/LocaleListTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/LocaleTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/LocaleTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/LocaleTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/LocaleTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/MultiParagraphIntegrationTest.kt
similarity index 99%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/MultiParagraphIntegrationTest.kt
index 1b09373..34e0e0a 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/MultiParagraphIntegrationTest.kt
@@ -29,7 +29,7 @@
 import androidx.ui.text.style.TextDirectionAlgorithm
 import androidx.ui.text.style.TextIndent
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.TextUnit
 import androidx.ui.unit.em
 import androidx.ui.unit.sp
@@ -224,7 +224,7 @@
                 val x = fontSizeInPx * col
 
                 val actualOffset = paragraph.getOffsetForPosition(
-                    PxPosition(x.toFloat(), y.toFloat())
+                    Offset(x.toFloat(), y.toFloat())
                 )
                 assertWithMessage("getOffsetForPosition($x, $y) failed")
                     .that(actualOffset).isEqualTo(i)
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphIntegrationTest.kt
similarity index 98%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphIntegrationTest.kt
index 7eba737..c99024a 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphIntegrationTest.kt
@@ -18,7 +18,6 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.ui.geometry.Offset
 import androidx.ui.geometry.Rect
 import androidx.ui.graphics.Canvas
 import androidx.ui.graphics.Color
@@ -41,7 +40,7 @@
 import androidx.ui.text.style.TextGeometricTransform
 import androidx.ui.text.style.TextIndent
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.em
 import androidx.ui.unit.sp
 import com.google.common.truth.Truth.assertThat
@@ -226,7 +225,7 @@
 
             // test positions that are 1, fontSize+1, 2fontSize+1 which maps to chars 0, 1, 2 ...
             for (i in 0..text.length) {
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx / 2))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx / 2))
                 val offset = paragraph.getOffsetForPosition(position)
                 assertWithMessage("offset at index $i, position $position does not match")
                     .that(offset).isEqualTo(i)
@@ -248,7 +247,7 @@
 
             // test positions that are 1, fontSize+1, 2fontSize+1 which maps to chars .., 2, 1, 0
             for (i in 0..text.length) {
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx / 2))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx / 2))
                 val offset = paragraph.getOffsetForPosition(position)
                 assertWithMessage("offset at index $i, position $position does not match")
                     .that(offset).isEqualTo(text.length - i)
@@ -273,7 +272,7 @@
             // test positions are 1, fontSize+1, 2fontSize+1 and always on the second line
             // which maps to chars 3, 4, 5
             for (i in 0..secondLine.length) {
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx * 1.5f))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx * 1.5f))
                 val offset = paragraph.getOffsetForPosition(position)
                 assertWithMessage(
                     "offset at index $i, position $position, second line does not match"
@@ -299,7 +298,7 @@
             // test positions are 1, fontSize+1, 2fontSize+1 and always on the second line
             // which maps to chars 5, 4, 3
             for (i in 0..secondLine.length) {
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx * 1.5f))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx * 1.5f))
                 val offset = paragraph.getOffsetForPosition(position)
                 assertWithMessage(
                     "offset at index $i, position $position, second line does not match"
@@ -321,12 +320,12 @@
             )
 
             // greater than width
-            var position = PxPosition((fontSizeInPx * text.length * 2), (fontSizeInPx / 2))
+            var position = Offset((fontSizeInPx * text.length * 2), (fontSizeInPx / 2))
             var offset = paragraph.getOffsetForPosition(position)
             assertThat(offset).isEqualTo(text.length)
 
             // negative
-            position = PxPosition((-1 * fontSizeInPx), (fontSizeInPx / 2))
+            position = Offset((-1 * fontSizeInPx), (fontSizeInPx / 2))
             offset = paragraph.getOffsetForPosition(position)
             assertThat(offset).isZero()
         }
@@ -345,12 +344,12 @@
             )
 
             // greater than height
-            var position = PxPosition((fontSizeInPx / 2), (fontSizeInPx * text.length * 2))
+            var position = Offset((fontSizeInPx / 2), (fontSizeInPx * text.length * 2))
             var offset = paragraph.getOffsetForPosition(position)
             assertThat(offset).isZero()
 
             // negative
-            position = PxPosition((fontSizeInPx / 2), (-1 * fontSizeInPx))
+            position = Offset((fontSizeInPx / 2), (-1 * fontSizeInPx))
             offset = paragraph.getOffsetForPosition(position)
             assertThat(offset).isZero()
         }
@@ -2208,7 +2207,7 @@
             )
 
             // The position of the last character in display order.
-            val position = PxPosition(("a.".length * fontSizeInPx + 1), (fontSizeInPx / 2))
+            val position = Offset(("a.".length * fontSizeInPx + 1), (fontSizeInPx / 2))
             val charIndex = paragraph.getOffsetForPosition(position)
             assertThat(charIndex).isEqualTo(2)
         }
@@ -2232,7 +2231,7 @@
             )
 
             // The position of the first character in display order.
-            val position = PxPosition((fontSizeInPx / 2 + 1), (fontSizeInPx / 2))
+            val position = Offset((fontSizeInPx / 2 + 1), (fontSizeInPx / 2))
             val charIndex = paragraph.getOffsetForPosition(position)
             assertThat(charIndex).isEqualTo(2)
         }
@@ -2254,7 +2253,7 @@
 
             for (i in 0..text.length) {
                 // The position of the i-th character in display order.
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx / 2))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx / 2))
                 val charIndex = paragraph.getOffsetForPosition(position)
                 assertThat(charIndex).isEqualTo(i)
             }
@@ -2277,7 +2276,7 @@
 
             for (i in text.indices) {
                 // The position of the i-th character in display order.
-                val position = PxPosition((i * fontSizeInPx + 1), (fontSizeInPx / 2))
+                val position = Offset((i * fontSizeInPx + 1), (fontSizeInPx / 2))
                 val charIndex = paragraph.getOffsetForPosition(position)
                 assertThat(charIndex).isEqualTo(i)
             }
@@ -2299,7 +2298,7 @@
             )
 
             // The first character in display order should be '.'
-            val position = PxPosition((fontSizeInPx / 2 + 1), (fontSizeInPx / 2))
+            val position = Offset((fontSizeInPx / 2 + 1), (fontSizeInPx / 2))
             val index = paragraph.getOffsetForPosition(position)
             assertThat(index).isEqualTo(2)
         }
@@ -3117,7 +3116,7 @@
 
             // This position should point to the first character 'a' if indent is applied.
             // Otherwise this position will point to the second character 'b'.
-            val position = PxPosition((indentInPx + 1), (fontSizeInPx / 2))
+            val position = Offset((indentInPx + 1), (fontSizeInPx / 2))
             // The offset corresponding to the position should be the first char 'a'.
             assertThat(paragraph.getOffsetForPosition(position)).isZero()
         }
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphIntrinsicIntegrationTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphPlaceholderIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphPlaceholderIntegrationTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/ParagraphPlaceholderIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/ParagraphPlaceholderIntegrationTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/StringTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/StringTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/StringTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/StringTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextDelegateIntegrationTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextDelegateIntegrationTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextLayoutResultIntegrationTest.kt
similarity index 96%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextLayoutResultIntegrationTest.kt
index 9052592..a10c47a 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextLayoutResultIntegrationTest.kt
@@ -25,7 +25,7 @@
 import androidx.ui.text.font.asFontFamily
 import androidx.ui.text.matchers.isZero
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.sp
 import com.google.common.truth.Truth.assertThat
@@ -133,7 +133,7 @@
         )
         val layoutResult = textDelegate.layout(Constraints(), layoutDirection)
 
-        val selection = layoutResult.getOffsetForPosition(PxPosition.Origin)
+        val selection = layoutResult.getOffsetForPosition(Offset.Zero)
 
         assertThat(selection).isZero()
     }
@@ -159,7 +159,7 @@
             val layoutResult = textDelegate.layout(Constraints(), layoutDirection)
 
             val selection = layoutResult.getOffsetForPosition(
-                position = PxPosition((fontSize.toPx() * characterIndex + 1), 0f)
+                position = Offset((fontSize.toPx() * characterIndex + 1), 0f)
             )
 
             assertThat(selection).isEqualTo(characterIndex)
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextTestExtensions.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextTestExtensions.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/TextTestExtensions.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/TextTestExtensions.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/BitmapSubject.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/BitmapSubject.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/BitmapSubject.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/BitmapSubject.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/CharSequenceSubject.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/CharSequenceSubject.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/CharSequenceSubject.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/CharSequenceSubject.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/ComposeMatchers.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/ComposeMatchers.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/ComposeMatchers.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/ComposeMatchers.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/TypefaceSubject.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/TypefaceSubject.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/matchers/TypefaceSubject.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/matchers/TypefaceSubject.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidParagraphTest.kt
similarity index 98%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidParagraphTest.kt
index 7e5abe6..ee50ea5 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidParagraphTest.kt
@@ -638,8 +638,8 @@
         assertThat(paragraph.charSequence)
             .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
                 return@hasSpan it.color == color.toArgb() &&
-                        it.offsetX == offset.dx &&
-                        it.offsetY == offset.dy &&
+                        it.offsetX == offset.x &&
+                        it.offsetY == offset.y &&
                         it.radius == radius
             }
     }
@@ -671,15 +671,15 @@
         assertThat(paragraph.charSequence)
             .hasSpan(ShadowSpan::class, start = 0, end = text.length) {
                 return@hasSpan it.color == color.toArgb() &&
-                        it.offsetX == offset.dx &&
-                        it.offsetY == offset.dy &&
+                        it.offsetX == offset.x &&
+                        it.offsetY == offset.y &&
                         it.radius == radius
             }
         assertThat(paragraph.charSequence)
             .hasSpanOnTop(ShadowSpan::class, start = 0, end = "abc".length) {
                 return@hasSpanOnTop it.color == colorOverwrite.toArgb() &&
-                        it.offsetX == offsetOverwrite.dx &&
-                        it.offsetY == offsetOverwrite.dy &&
+                        it.offsetX == offsetOverwrite.x &&
+                        it.offsetY == offsetOverwrite.y &&
                         it.radius == radiusOverwrite
             }
     }
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceCacheTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceCacheTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceCacheTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceCacheTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt
similarity index 98%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt
index f007b69..92cffca 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceSubsetTest.kt
@@ -26,7 +26,6 @@
 import androidx.ui.text.font.FontWeight
 import androidx.ui.text.font.fontFamily
 import androidx.ui.text.matchers.assertThat
-import androidx.ui.text.typefaceFromFontFamily
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.junit.MockitoJUnitRunner
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceTest.kt
similarity index 99%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceTest.kt
index 6adbe70..8b66324 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidTypefaceTest.kt
+++ b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/AndroidTypefaceTest.kt
@@ -33,7 +33,6 @@
 import androidx.ui.text.font.fontFamily
 import androidx.ui.text.matchers.assertThat
 import androidx.ui.text.core.test.R
-import androidx.ui.text.typefaceFromFontFamily
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.eq
@@ -514,4 +513,4 @@
         assertThat(typeface500.isBold).isFalse()
         assertThat(typeface600.isBold).isTrue()
     }
-}
\ No newline at end of file
+}
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/GenerifFontFamilyCacheTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/GenerifFontFamilyCacheTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/GenerifFontFamilyCacheTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/GenerifFontFamilyCacheTest.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/TextTestExtensions.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/TextTestExtensions.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/TextTestExtensions.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/TextTestExtensions.kt
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/TypefaceAdapterTest.kt b/ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/TypefaceAdapterTest.kt
similarity index 100%
rename from ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/TypefaceAdapterTest.kt
rename to ui/ui-text-core/src/androidAndroidTest/kotlin/androidx/ui/text/platform/TypefaceAdapterTest.kt
diff --git a/ui/ui-text-core/src/main/AndroidManifest.xml b/ui/ui-text-core/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-text-core/src/main/AndroidManifest.xml
rename to ui/ui-text-core/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidDefaultTypeface.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidDefaultTypeface.kt
similarity index 92%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidDefaultTypeface.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidDefaultTypeface.kt
index 727882b..7c0bdf3 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidDefaultTypeface.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidDefaultTypeface.kt
@@ -37,7 +37,8 @@
         synthesis: FontSynthesis
     ): Typeface {
         return if (Build.VERSION.SDK_INT < 28) {
-            Typeface.defaultFromStyle(TypefaceAdapter.getTypefaceStyle(fontWeight, fontStyle))
+            Typeface.defaultFromStyle(
+                TypefaceAdapter.getTypefaceStyle(fontWeight, fontStyle))
         } else {
             Typeface.create(Typeface.DEFAULT, fontWeight.weight, fontStyle == FontStyle.Italic)
         }
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidFontListTypeface.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidFontListTypeface.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidFontListTypeface.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidFontListTypeface.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt
similarity index 95%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt
index c5586d2..fe3909f 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidGenericFontFamilyTypeface.kt
@@ -67,7 +67,8 @@
 
     private fun buildStyledTypeface(fontWeight: FontWeight, fontStyle: FontStyle) =
         if (Build.VERSION.SDK_INT < 28) {
-            Typeface.create(nativeTypeface, TypefaceAdapter.getTypefaceStyle(fontWeight, fontStyle))
+            Typeface.create(nativeTypeface,
+                TypefaceAdapter.getTypefaceStyle(fontWeight, fontStyle))
         } else {
             Typeface.create(nativeTypeface, fontWeight.weight, fontStyle == FontStyle.Italic)
         }
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidLocaleDelegate.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidLocaleDelegate.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidLocaleDelegate.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidLocaleDelegate.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
similarity index 90%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
index 7da4b28..e461889 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
@@ -19,6 +19,19 @@
 import android.text.TextPaint
 import android.text.TextUtils
 import androidx.annotation.VisibleForTesting
+import androidx.ui.geometry.Rect
+import androidx.ui.graphics.Canvas
+import androidx.ui.graphics.Path
+import androidx.ui.graphics.asComposePath
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.Paragraph
+import androidx.ui.text.ParagraphConstraints
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.Placeholder
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.TextRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.font.Font
 import androidx.ui.text.platform.LayoutCompat.ALIGN_CENTER
 import androidx.ui.text.platform.LayoutCompat.ALIGN_LEFT
 import androidx.ui.text.platform.LayoutCompat.ALIGN_NORMAL
@@ -30,21 +43,10 @@
 import androidx.ui.text.platform.LayoutCompat.JUSTIFICATION_MODE_INTER_WORD
 import androidx.ui.text.platform.selection.WordBoundary
 import androidx.ui.text.platform.style.PlaceholderSpan
-import androidx.ui.geometry.Rect
-import androidx.ui.graphics.Canvas
-import androidx.ui.graphics.Path
-import androidx.ui.graphics.asComposePath
-import androidx.ui.text.AnnotatedString
-import androidx.ui.text.Paragraph
-import androidx.ui.text.ParagraphConstraints
-import androidx.ui.text.Placeholder
-import androidx.ui.text.SpanStyle
-import androidx.ui.text.TextRange
-import androidx.ui.text.TextStyle
 import androidx.ui.text.style.TextAlign
 import androidx.ui.text.style.TextDirection
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import java.util.Locale as JavaLocale
 
 /**
@@ -205,7 +207,7 @@
     internal val textPaint: TextPaint
         get() = paragraphIntrinsics.textPaint
 
-    override fun getOffsetForPosition(position: PxPosition): Int {
+    override fun getOffsetForPosition(position: Offset): Int {
         val line = layout.getLineForVertical(position.y.toInt())
         return layout.getOffsetForHorizontal(line, position.x)
     }
@@ -333,3 +335,43 @@
     TextAlign.End -> ALIGN_OPPOSITE
     else -> DEFAULT_ALIGNMENT
 }
+
+internal actual fun ActualParagraph(
+    text: String,
+    style: TextStyle,
+    spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+    placeholders: List<AnnotatedString.Range<Placeholder>>,
+    maxLines: Int,
+    ellipsis: Boolean,
+    constraints: ParagraphConstraints,
+    density: Density,
+    resourceLoader: Font.ResourceLoader
+): Paragraph {
+    return AndroidParagraph(
+        text = text,
+        style = style,
+        spanStyles = spanStyles,
+        placeholders = placeholders,
+        maxLines = maxLines,
+        ellipsis = ellipsis,
+        constraints = constraints,
+        typefaceAdapter = TypefaceAdapter(
+            resourceLoader = resourceLoader
+        ),
+        density = density
+    )
+}
+
+internal actual fun ActualParagraph(
+    paragraphIntrinsics: ParagraphIntrinsics,
+    maxLines: Int,
+    ellipsis: Boolean,
+    constraints: ParagraphConstraints
+): Paragraph {
+    return AndroidParagraph(
+        paragraphIntrinsics = paragraphIntrinsics as AndroidParagraphIntrinsics,
+        maxLines = maxLines,
+        ellipsis = ellipsis,
+        constraints = constraints
+    )
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphHelper.kt
similarity index 98%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphHelper.kt
index 4471c7c..db229da 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphHelper.kt
@@ -74,7 +74,6 @@
     typefaceAdapter: TypefaceAdapter,
     density: Density
 ): SpanStyle {
-
     when (style.fontSize.type) {
         TextUnitType.Sp -> with(density) {
             textSize = style.fontSize.toPx()
@@ -123,8 +122,8 @@
     style.shadow?.let {
         setShadowLayer(
             it.blurRadius,
-            it.offset.dx,
-            it.offset.dy,
+            it.offset.x,
+            it.offset.y,
             it.color.toArgb()
         )
     }
@@ -420,7 +419,7 @@
         }
         style.shadow?.let {
             spannableString.setSpan(
-                ShadowSpan(it.color.toArgb(), it.offset.dx, it.offset.dy, it.blurRadius),
+                ShadowSpan(it.color.toArgb(), it.offset.x, it.offset.y, it.blurRadius),
                 start,
                 end,
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
similarity index 81%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
index ae1b8145..392c74a 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
@@ -24,6 +24,7 @@
 import androidx.ui.text.Placeholder
 import androidx.ui.text.SpanStyle
 import androidx.ui.text.TextStyle
+import androidx.ui.text.font.Font
 
 internal class AndroidParagraphIntrinsics(
     val text: String,
@@ -79,3 +80,21 @@
         layoutIntrinsics = LayoutIntrinsics(charSequence, textPaint, textDirectionHeuristic)
     }
 }
+
+internal actual fun ActualParagraphIntrinsics(
+    text: String,
+    style: TextStyle,
+    spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+    placeholders: List<AnnotatedString.Range<Placeholder>>,
+    density: Density,
+    resourceLoader: Font.ResourceLoader
+): ParagraphIntrinsics = AndroidParagraphIntrinsics(
+        text = text,
+        style = style,
+        placeholders = placeholders,
+        typefaceAdapter = TypefaceAdapter(
+            resourceLoader = resourceLoader
+        ),
+        spanStyles = spanStyles,
+        density = density
+    )
\ No newline at end of file
diff --git a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidPlatformLocale.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidPlatformLocale.kt
new file mode 100644
index 0000000..c3b2030cc
--- /dev/null
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidPlatformLocale.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.text.platform
+
+import android.os.Build
+
+internal actual fun createPlatformLocaleDelegate() =
+    if (Build.VERSION.SDK_INT >= 24) {
+        AndroidLocaleDelegateAPI24()
+    } else {
+        AndroidLocaleDelegateAPI23()
+    }
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidStringDelegate.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidStringDelegate.kt
similarity index 92%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidStringDelegate.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidStringDelegate.kt
index 1dfd6c5..855d5d5 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidStringDelegate.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidStringDelegate.kt
@@ -33,4 +33,7 @@
 
     override fun decapitalize(string: String, locale: PlatformLocale): String =
         string.decapitalize()
-}
\ No newline at end of file
+}
+
+internal actual fun ActualStringDelegate(): PlatformStringDelegate =
+    AndroidStringDelegate()
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidTypeface.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidTypeface.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidTypeface.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidTypeface.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/TypefaceAdapter.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/TypefaceAdapter.kt
similarity index 89%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/TypefaceAdapter.kt
rename to ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/TypefaceAdapter.kt
index 8da6a54..29c8247f0 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/TypefaceAdapter.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/TypefaceAdapter.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.text.platform
 
+import android.content.Context
 import android.graphics.Typeface
 import android.os.Build
 import androidx.collection.LruCache
@@ -253,3 +254,31 @@
         return synthesize(typeface, font, fontWeight, fontStyle, fontSynthesis)
     }
 }
+
+/**
+ * Android specific Typeface builder function from FontFamily.
+ *
+ * You can pass necessaryStyles for loading only specific styles. The font style matching happens
+ * only with the loaded Typeface.
+ *
+ * This function caches the internal native Typeface but always create the new Typeface object.
+ * Caller should cache if necessary.
+ *
+ * @param context the context to be used for loading Typeface.
+ * @param fontFamily the font family to be loaded
+ * @param necessaryStyles optional style filter for loading subset of fontFamily. null means load
+ *                        all fonts in fontFamily.
+ * @return A loaded Typeface.
+ */
+fun typefaceFromFontFamily(
+    context: Context,
+    fontFamily: FontFamily,
+    necessaryStyles: List<Pair<FontWeight, FontStyle>>? = null
+): androidx.ui.text.Typeface {
+    return when (fontFamily) {
+        is FontListFontFamily -> AndroidFontListTypeface(fontFamily, context, necessaryStyles)
+        is GenericFontFamily -> AndroidGenericFontFamilyTypeface(fontFamily)
+        is DefaultFontFamily -> AndroidDefaultTypeface()
+        is LoadedFontFamily -> fontFamily.typeface
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/EditOperation.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditOperation.kt
similarity index 91%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/EditOperation.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditOperation.kt
index 9e497924..a11a949 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/EditOperation.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditOperation.kt
@@ -16,10 +16,9 @@
 
 package androidx.ui.input
 
-import java.text.BreakIterator
-import java.util.Objects
-import kotlin.math.max
-import kotlin.math.min
+import androidx.ui.util.isSurrogatePair
+import androidx.ui.util.findFollowingBreak
+import androidx.ui.util.findPrecedingBreak
 
 /**
  * A base class of all EditOperations
@@ -181,11 +180,11 @@
     override fun process(buffer: EditingBuffer) {
         buffer.delete(
             buffer.selectionEnd,
-            min(buffer.selectionEnd + afterLength, buffer.length)
+            minOf(buffer.selectionEnd + afterLength, buffer.length)
         )
 
         buffer.delete(
-            max(0, buffer.selectionStart - beforeLength),
+            maxOf(0, buffer.selectionStart - beforeLength),
             buffer.selectionStart
         )
     }
@@ -206,7 +205,7 @@
     val afterLength: Int
 ) : EditOperation {
     override fun process(buffer: EditingBuffer) {
-        // Convert code point length into Java character length. Then call the common logic of the
+        // Convert code point length into character length. Then call the common logic of the
         // DeleteSurroundingTextEditOp
         var beforeLenInChars = 0
         for (i in 0 until beforeLength) {
@@ -215,7 +214,7 @@
                 val lead = buffer[buffer.selectionStart - beforeLenInChars - 1]
                 val trail = buffer[buffer.selectionStart - beforeLenInChars]
 
-                if (Character.isSurrogatePair(lead, trail)) {
+                if (isSurrogatePair(lead, trail)) {
                     beforeLenInChars++
                 }
             }
@@ -229,7 +228,7 @@
                 val lead = buffer[buffer.selectionEnd + afterLenInChars - 1]
                 val trail = buffer[buffer.selectionEnd + afterLenInChars]
 
-                if (Character.isSurrogatePair(lead, trail)) {
+                if (isSurrogatePair(lead, trail)) {
                     afterLenInChars++
                 }
             }
@@ -240,6 +239,7 @@
         buffer.delete(buffer.selectionStart - beforeLenInChars, buffer.selectionStart)
     }
 }
+
 /**
  * An edit operation represents setSelection callback from InputMethod
  *
@@ -281,7 +281,7 @@
     // Class with empty arguments default ctor cannot be data class.
     // Treating all FinishComposingTextEditOp are equal object.
     override fun equals(other: Any?): Boolean = other is FinishComposingTextEditOp
-    override fun hashCode(): Int = Objects.hashCode(this.javaClass)
+    override fun hashCode(): Int = this::class.hashCode()
 }
 
 /**
@@ -311,16 +311,14 @@
             return
         }
 
-        val it = BreakIterator.getCharacterInstance()
-        it.setText(buffer.toString())
-        val prevCursorPos = it.preceding(buffer.cursor)
+        val prevCursorPos = buffer.toString().findPrecedingBreak(buffer.cursor)
         buffer.delete(prevCursorPos, buffer.cursor)
     }
 
     // Class with empty arguments default ctor cannot be data class.
     // Treating all FinishComposingTextEditOp are equal object.
     override fun equals(other: Any?): Boolean = other is BackspaceKeyEditOp
-    override fun hashCode(): Int = Objects.hashCode(this.javaClass)
+    override fun hashCode(): Int = this::class.hashCode()
 }
 
 /**
@@ -339,23 +337,22 @@
 ) : EditOperation {
 
     override fun process(buffer: EditingBuffer) {
-        val it = BreakIterator.getCharacterInstance()
-        it.setText(buffer.toString())
         if (buffer.cursor == -1) {
             buffer.cursor = buffer.selectionStart
         }
 
         var newCursor = buffer.selectionStart
+        val bufferText = buffer.toString()
         if (amount > 0) {
             for (i in 0 until amount) {
-                val next = it.following(newCursor)
-                if (next == BreakIterator.DONE) break
-                newCursor = next
-            }
+                val next = bufferText.findFollowingBreak(newCursor)
+                if (next == -1) break
+                    newCursor = next
+                }
         } else {
             for (i in 0 until -amount) {
-                val prev = it.preceding(newCursor)
-                if (prev == BreakIterator.DONE) break
+                val prev = bufferText.findPrecedingBreak(newCursor)
+                if (prev == -1) break
                 newCursor = prev
             }
         }
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/EditProcessor.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditProcessor.kt
similarity index 95%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/EditProcessor.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditProcessor.kt
index fc8ba0b..2d346e4 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/EditProcessor.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditProcessor.kt
@@ -16,8 +16,7 @@
 
 package androidx.ui.input
 
-import androidx.annotation.RestrictTo
-import androidx.annotation.VisibleForTesting
+import androidx.ui.util.annotation.VisibleForTesting
 import androidx.ui.text.TextRange
 
 /**
@@ -27,7 +26,6 @@
  * IME.
  * @suppress
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 class EditProcessor {
 
     // The previous editor state we passed back to the user of this class.
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/EditingBuffer.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditingBuffer.kt
similarity index 99%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/EditingBuffer.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditingBuffer.kt
index 833ff11..32ee78c 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/EditingBuffer.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditingBuffer.kt
@@ -17,7 +17,6 @@
 package androidx.ui.input
 
 import androidx.ui.text.TextRange
-import java.lang.IllegalArgumentException
 
 /**
  * The editing buffer
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/EditorValue.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditorValue.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/EditorValue.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/EditorValue.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/GapBuffer.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/GapBuffer.kt
similarity index 94%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/GapBuffer.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/GapBuffer.kt
index 4df02be..a65cb12 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/GapBuffer.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/GapBuffer.kt
@@ -16,10 +16,18 @@
 
 package androidx.ui.input
 
-import android.util.Log
-import androidx.annotation.RestrictTo
-import kotlin.math.max
-import kotlin.math.min
+private fun String.toCharArray(
+    destination: CharArray,
+    destinationOffset: Int = 0,
+    startIndex: Int = 0,
+    endIndex: Int = this.length
+) {
+    var index = startIndex
+    while (index < endIndex) {
+        destination[destinationOffset + index - startIndex] = this[index]
+        index++
+    }
+}
 
 /**
  * The gap buffer implementation
@@ -82,12 +90,6 @@
             newCapacity *= 2
         }
 
-        //
-        if (newCapacity >= 512 * 1024) {
-            Log.w("GapBuffer",
-                "Allocating $newCapacity buffer. Consider alternative data structure.")
-        }
-
         val newBuffer = CharArray(newCapacity)
         buffer.copyInto(newBuffer, 0, 0, gapStart)
         val tailLength = capacity - gapEnd
@@ -209,7 +211,6 @@
  * @param text The initial text
  * @suppress
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
 class PartialGapBuffer(var text: String) {
     internal companion object {
         const val BUF_SIZE = 255
@@ -240,11 +241,11 @@
     fun replace(start: Int, end: Int, text: String) {
         val buffer = buffer
         if (buffer == null) { // First time to create gap buffer
-            val charArray = CharArray(max(BUF_SIZE, text.length + 2 * SURROUNDING_SIZE))
+            val charArray = CharArray(maxOf(BUF_SIZE, text.length + 2 * SURROUNDING_SIZE))
 
             // Convert surrounding text into buffer.
-            val leftCopyCount = min(start, SURROUNDING_SIZE)
-            val rightCopyCount = min(this.text.length - end, SURROUNDING_SIZE)
+            val leftCopyCount = minOf(start, SURROUNDING_SIZE)
+            val rightCopyCount = minOf(this.text.length - end, SURROUNDING_SIZE)
 
             // Copy left surrounding
             this.text.toCharArray(charArray, 0, start - leftCopyCount, start)
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/ImeAction.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/ImeAction.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/ImeAction.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/ImeAction.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/InputEventListener.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/InputEventListener.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/InputEventListener.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/InputEventListener.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/KeyboardType.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/KeyboardType.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/KeyboardType.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/KeyboardType.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/OWNERS b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/OWNERS
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/OWNERS
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/OWNERS
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/TextInputService.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/TextInputService.kt
similarity index 96%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/TextInputService.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/TextInputService.kt
index 2a36044..111f5cd 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/TextInputService.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/TextInputService.kt
@@ -16,9 +16,7 @@
 
 package androidx.ui.input
 
-import androidx.annotation.RestrictTo
 import androidx.ui.geometry.Rect
-import org.jetbrains.annotations.TestOnly
 
 /**
  * The input session token.
@@ -156,9 +154,7 @@
     fun notifyFocusedRect(rect: Rect)
 }
 
-/** @suppress */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API")
 var textInputServiceFactory: (PlatformTextInputService) -> TextInputService =
     { TextInputService(it) }
-    @TestOnly
     set
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/input/VisualTransformation.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/VisualTransformation.kt
similarity index 97%
rename from ui/ui-text-core/src/main/java/androidx/ui/input/VisualTransformation.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/VisualTransformation.kt
index cdb8c24..4ea3255 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/input/VisualTransformation.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/input/VisualTransformation.kt
@@ -130,7 +130,7 @@
 data class PasswordVisualTransformation(val mask: Char = '\u2022') : VisualTransformation {
     override fun filter(text: AnnotatedString): TransformedText {
         return TransformedText(
-            AnnotatedString(Character.toString(mask).repeat(text.text.length)),
+            AnnotatedString(mask.toString().repeat(text.text.length)),
             OffsetMap.identityOffsetMap
         )
     }
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/AnnotatedString.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/AnnotatedString.kt
similarity index 93%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/AnnotatedString.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/AnnotatedString.kt
index b58d03f..a50c500 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/AnnotatedString.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/AnnotatedString.kt
@@ -21,9 +21,6 @@
 import androidx.ui.text.AnnotatedString.Builder
 import androidx.ui.text.AnnotatedString.Range
 import androidx.ui.util.fastForEach
-import java.util.SortedSet
-import kotlin.math.max
-import kotlin.math.min
 
 /**
  * The class changes the character level style of the specified range.
@@ -553,54 +550,9 @@
  * @param transform the transformation method
  * @return newly allocated transformed AnnotatedString
  */
-private fun AnnotatedString.transform(transform: (String, Int, Int) -> String): AnnotatedString {
-    val transitions = sortedSetOf(0, text.length)
-    collectRangeTransitions(spanStyles, transitions)
-    collectRangeTransitions(paragraphStyles, transitions)
-
-    var resultStr = ""
-    val offsetMap = mutableMapOf(0 to 0)
-    transitions.windowed(size = 2) { (start, end) ->
-        resultStr += transform(text, start, end)
-        offsetMap.put(end, resultStr.length)
-    }
-
-    val newSpanStyles = spanStyles.map {
-        // The offset map must have mapping entry from all style start, end position.
-        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
-    }
-    val newParaStyles = paragraphStyles.map {
-        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
-    }
-    val newAnnotations = annotations.map {
-        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
-    }
-
-    return AnnotatedString(
-        text = resultStr,
-        spanStyles = newSpanStyles,
-        paragraphStyles = newParaStyles,
-        annotations = newAnnotations
-    )
-}
-
-/**
- * Adds all [AnnotatedString.Range] transition points
- *
- * @param ranges The list of AnnotatedString.Range
- * @param target The output list
- */
-private fun <T> collectRangeTransitions(
-    ranges: List<Range<T>>,
-    target: SortedSet<Int>
-) {
-    ranges.fold(target) { acc, range ->
-        acc.apply {
-            add(range.start)
-            add(range.end)
-        }
-    }
-}
+internal expect fun AnnotatedString.transform(
+    transform: (String, Int, Int) -> String
+): AnnotatedString
 
 /**
  * Returns the length of the [AnnotatedString].
@@ -669,8 +621,8 @@
     return ranges.filter { intersect(start, end, it.start, it.end) }.map {
         Range(
             item = it.item,
-            start = max(start, it.start) - start,
-            end = min(end, it.end) - start,
+            start = maxOf(start, it.start) - start,
+            end = minOf(end, it.end) - start,
             tag = it.tag
         )
     }
@@ -769,5 +721,5 @@
  * @return [lStart, lEnd) intersects with range [rStart, rEnd), vice versa.
  */
 internal fun intersect(lStart: Int, lEnd: Int, rStart: Int, rEnd: Int) =
-    max(lStart, rStart) < min(lEnd, rEnd) ||
+    maxOf(lStart, rStart) < minOf(lEnd, rEnd) ||
             contains(lStart, lEnd, rStart, rEnd) || contains(rStart, rEnd, lStart, lEnd)
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/Locale.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Locale.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/Locale.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Locale.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/LocaleList.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/LocaleList.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/LocaleList.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/LocaleList.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/MultiParagraph.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/MultiParagraph.kt
similarity index 98%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/MultiParagraph.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/MultiParagraph.kt
index ebe528c..61ac1fe 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/MultiParagraph.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/MultiParagraph.kt
@@ -16,14 +16,13 @@
 
 package androidx.ui.text
 
-import androidx.ui.geometry.Offset
 import androidx.ui.geometry.Rect
 import androidx.ui.graphics.Canvas
 import androidx.ui.graphics.Path
 import androidx.ui.text.font.Font
 import androidx.ui.text.style.TextDirection
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.util.fastForEach
 import kotlin.math.max
 
@@ -266,7 +265,7 @@
     }
 
     /** Returns the character offset closest to the given graphical position. */
-    fun getOffsetForPosition(position: PxPosition): Int {
+    fun getOffsetForPosition(position: Offset): Int {
         val paragraphIndex = when {
             position.y <= 0f -> 0
             position.y >= height -> paragraphInfoList.lastIndex
@@ -694,11 +693,11 @@
     }
 
     /**
-     * Convert a [PxPosition] relative to the parent [MultiParagraph] to the local [PxPosition]
+     * Convert a [Offset] relative to the parent [MultiParagraph] to the local [Offset]
      * relative to the [paragraph].
      */
-    fun PxPosition.toLocal(): PxPosition {
-        return PxPosition(x = x, y = y - top)
+    fun Offset.toLocal(): Offset {
+        return Offset(x, y - top)
     }
 
     /**
@@ -706,7 +705,7 @@
      * [MultiParagraph].
      */
     fun Rect.toGlobal(): Rect {
-        return shift(Offset(dx = 0f, dy = this@ParagraphInfo.top))
+        return shift(Offset(0f, this@ParagraphInfo.top))
     }
 
     /**
@@ -716,7 +715,7 @@
      * Notice that this function changes the input value.
      */
     fun Path.toGlobal(): Path {
-        shift(Offset(dx = 0f, dy = top))
+        shift(Offset(0f, top))
         return this
     }
 
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/MultiParagraphIntrinsics.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/MultiParagraphIntrinsics.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/MultiParagraphIntrinsics.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/Paragraph.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Paragraph.kt
similarity index 91%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/Paragraph.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Paragraph.kt
index 29c3c08..8f03d73 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/Paragraph.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Paragraph.kt
@@ -19,12 +19,10 @@
 import androidx.ui.graphics.Canvas
 import androidx.ui.graphics.Path
 import androidx.ui.text.font.Font
-import androidx.ui.text.platform.AndroidParagraph
-import androidx.ui.text.platform.AndroidParagraphIntrinsics
-import androidx.ui.text.platform.TypefaceAdapter
+import androidx.ui.text.platform.ActualParagraph
 import androidx.ui.text.style.TextDirection
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 internal const val DefaultMaxLines = Int.MAX_VALUE
 
@@ -204,7 +202,7 @@
     fun getBidiRunDirection(offset: Int): TextDirection
 
     /** Returns the character offset closest to the given graphical position. */
-    fun getOffsetForPosition(position: PxPosition): Int
+    fun getOffsetForPosition(position: Offset): Int
 
     /**
      * Returns the bounding box as Rect of the character for given character offset. Rect
@@ -244,7 +242,7 @@
  *
  * @throws IllegalArgumentException if [ParagraphStyle.textDirectionAlgorithm] is not set
  */
-/* actual */ fun Paragraph(
+fun Paragraph(
     text: String,
     style: TextStyle,
     spanStyles: List<AnnotatedString.Range<SpanStyle>> = listOf(),
@@ -254,21 +252,17 @@
     constraints: ParagraphConstraints,
     density: Density,
     resourceLoader: Font.ResourceLoader
-): Paragraph {
-    return AndroidParagraph(
-        text = text,
-        style = style,
-        spanStyles = spanStyles,
-        placeholders = placeholders,
-        maxLines = maxLines,
-        ellipsis = ellipsis,
-        constraints = constraints,
-        typefaceAdapter = TypefaceAdapter(
-            resourceLoader = resourceLoader
-        ),
-        density = density
-    )
-}
+): Paragraph = ActualParagraph(
+    text,
+    style,
+    spanStyles,
+    placeholders,
+    maxLines,
+    ellipsis,
+    constraints,
+    density,
+    resourceLoader
+)
 
 /**
  * Lays out the text in [ParagraphIntrinsics] with the given constraints. A paragraph is a text
@@ -279,16 +273,14 @@
  * @param ellipsis whether to ellipsize text, applied only when [maxLines] is set
  * @param constraints how wide the text is allowed to be
  */
-/* actual */ fun Paragraph(
+fun Paragraph(
     paragraphIntrinsics: ParagraphIntrinsics,
     maxLines: Int = DefaultMaxLines,
     ellipsis: Boolean = false,
     constraints: ParagraphConstraints
-): Paragraph {
-    return AndroidParagraph(
-        paragraphIntrinsics = paragraphIntrinsics as AndroidParagraphIntrinsics,
-        maxLines = maxLines,
-        ellipsis = ellipsis,
-        constraints = constraints
-    )
-}
\ No newline at end of file
+): Paragraph = ActualParagraph(
+    paragraphIntrinsics,
+    maxLines,
+    ellipsis,
+    constraints
+)
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphConstraints.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphConstraints.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphConstraints.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphConstraints.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphIntrinsics.kt
similarity index 76%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphIntrinsics.kt
index b2248e3..c6869e7 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphIntrinsics.kt
@@ -17,8 +17,7 @@
 package androidx.ui.text
 
 import androidx.ui.text.font.Font
-import androidx.ui.text.platform.AndroidParagraphIntrinsics
-import androidx.ui.text.platform.TypefaceAdapter
+import androidx.ui.text.platform.ActualParagraphIntrinsics
 import androidx.ui.unit.Density
 
 /**
@@ -42,22 +41,18 @@
  *
  * @see ParagraphIntrinsics
  */
-/* actual */ fun ParagraphIntrinsics(
+fun ParagraphIntrinsics(
     text: String,
     style: TextStyle,
     spanStyles: List<AnnotatedString.Range<SpanStyle>> = listOf(),
     placeholders: List<AnnotatedString.Range<Placeholder>> = listOf(),
     density: Density,
     resourceLoader: Font.ResourceLoader
-): ParagraphIntrinsics {
-    return AndroidParagraphIntrinsics(
-        text = text,
-        style = style,
-        placeholders = placeholders,
-        typefaceAdapter = TypefaceAdapter(
-            resourceLoader = resourceLoader
-        ),
-        spanStyles = spanStyles,
-        density = density
-    )
-}
+): ParagraphIntrinsics = ActualParagraphIntrinsics(
+    text = text,
+    style = style,
+    spanStyles = spanStyles,
+    placeholders = placeholders,
+    density = density,
+    resourceLoader = resourceLoader
+)
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphStyle.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphStyle.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphStyle.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/ParagraphStyle.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/Placeholder.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Placeholder.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/Placeholder.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Placeholder.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/SoftwareKeyboardController.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/SoftwareKeyboardController.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/SoftwareKeyboardController.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/SoftwareKeyboardController.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/SpanStyle.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/SpanStyle.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/SpanStyle.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/SpanStyle.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/String.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/String.kt
similarity index 97%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/String.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/String.kt
index 44c1323..746f9e2 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/String.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/String.kt
@@ -16,8 +16,8 @@
 
 package androidx.ui.text
 
-import androidx.ui.text.platform.AndroidStringDelegate
 import androidx.ui.text.platform.PlatformLocale
+import androidx.ui.text.platform.ActualStringDelegate
 
 /**
  * Interface for providing platform dependent string related operations.
@@ -133,4 +133,4 @@
 fun String.decapitalize(localeList: LocaleList): String =
     if (localeList.isEmpty()) decapitalize(Locale.current) else decapitalize(localeList[0])
 
-private val stringDelegate = AndroidStringDelegate()
\ No newline at end of file
+private val stringDelegate = ActualStringDelegate()
\ No newline at end of file
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextDelegate.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextDelegate.kt
similarity index 92%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextDelegate.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextDelegate.kt
index 766fbdd..01dcfc1 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/TextDelegate.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextDelegate.kt
@@ -16,22 +16,19 @@
 
 package androidx.ui.text
 
-import androidx.annotation.RestrictTo
-import androidx.annotation.VisibleForTesting
+import androidx.ui.util.annotation.VisibleForTesting
 import androidx.ui.core.Constraints
 import androidx.ui.core.LayoutDirection
 import androidx.ui.core.constrain
 import androidx.ui.graphics.Canvas
 import androidx.ui.graphics.Paint
-import androidx.ui.text.TextDelegate.Companion.paint
 import androidx.ui.text.font.Font
 import androidx.ui.text.style.TextAlign
 import androidx.ui.text.style.TextOverflow
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.ceil
-import androidx.ui.unit.px
+import androidx.ui.unit.ipx
 
 /**
  * An object that paints text onto a [Canvas].
@@ -73,7 +70,6 @@
  *
  * @suppress
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 class TextDelegate(
     val text: AnnotatedString,
     val style: TextStyle,
@@ -98,14 +94,18 @@
      *
      * Valid only after [layout] has been called.
      */
-    val minIntrinsicWidth: IntPx get() = assumeIntrinsics { it.minIntrinsicWidth.px.ceil() }
+    val minIntrinsicWidth: IntPx get() = assumeIntrinsics {
+        kotlin.math.ceil(it.minIntrinsicWidth).toInt().ipx
+    }
 
     /**
      * The width at which increasing the width of the text no longer decreases the height.
      *
      * Valid only after [layout] has been called.
      */
-    val maxIntrinsicWidth: IntPx get() = assumeIntrinsics { it.maxIntrinsicWidth.px.ceil() }
+    val maxIntrinsicWidth: IntPx get() = assumeIntrinsics {
+        kotlin.math.ceil(it.maxIntrinsicWidth).toInt().ipx
+    }
 
     init {
         check(maxLines > 0)
@@ -181,7 +181,10 @@
                 copy(
                     layoutInput = layoutInput.copy(constraints = constraints),
                     size = constraints.constrain(
-                        IntPxSize(multiParagraph.width.px.ceil(), multiParagraph.height.px.ceil())
+                        IntPxSize(
+                            kotlin.math.ceil(multiParagraph.width).toInt().ipx,
+                            kotlin.math.ceil(multiParagraph.height).toInt().ipx
+                        )
                     )
                 )
             }
@@ -194,7 +197,10 @@
         )
 
         val size = constraints.constrain(
-            IntPxSize(multiParagraph.width.px.ceil(), multiParagraph.height.px.ceil())
+            IntPxSize(
+                kotlin.math.ceil(multiParagraph.width).toInt().ipx,
+                kotlin.math.ceil(multiParagraph.height).toInt().ipx
+            )
         )
 
         return TextLayoutResult(
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextLayoutHelper.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextLayoutHelper.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextLayoutHelper.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextLayoutHelper.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextLayoutResult.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextLayoutResult.kt
similarity index 98%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextLayoutResult.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextLayoutResult.kt
index 8df36d1..8705878 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/TextLayoutResult.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextLayoutResult.kt
@@ -25,7 +25,7 @@
 import androidx.ui.text.style.TextOverflow
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * The data class which holds the set of parameters of the text layout computation.
@@ -235,7 +235,7 @@
      *  @param position a graphical position in this text layout
      *  @return a character offset that is closest to the given graphical position.
      */
-    fun getOffsetForPosition(position: PxPosition): Int =
+    fun getOffsetForPosition(position: Offset): Int =
         multiParagraph.getOffsetForPosition(position)
 
     /**
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextPainter.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextPainter.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextPainter.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextPainter.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextRange.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextRange.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/TextStyle.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextStyle.kt
similarity index 99%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/TextStyle.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextStyle.kt
index 7bd0d66..c166570 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/TextStyle.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextStyle.kt
@@ -16,7 +16,7 @@
 
 package androidx.ui.text
 
-import androidx.annotation.VisibleForTesting
+import androidx.ui.util.annotation.VisibleForTesting
 import androidx.compose.Immutable
 import androidx.compose.Stable
 import androidx.ui.core.LayoutDirection
diff --git a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Typeface.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Typeface.kt
new file mode 100644
index 0000000..f4ab861
--- /dev/null
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/Typeface.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.text
+
+import androidx.ui.text.font.FontFamily
+
+/**
+ * A class that can be used for changing the font used in text.
+ */
+interface Typeface {
+    /**
+     * The font family used for creating this Typeface
+     */
+    val fontFamily: FontFamily
+}
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/Font.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/Font.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/Font.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/Font.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/FontFamily.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontFamily.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/FontFamily.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontFamily.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/FontMatcher.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontMatcher.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/FontMatcher.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontMatcher.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/FontStyle.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontStyle.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/FontStyle.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontStyle.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/FontSynthesis.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontSynthesis.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/FontSynthesis.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontSynthesis.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/font/FontWeight.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontWeight.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/font/FontWeight.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/font/FontWeight.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/PlatformLocale.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformLocale.kt
similarity index 89%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/platform/PlatformLocale.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformLocale.kt
index cf0b2ee..9cba92b 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/PlatformLocale.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformLocale.kt
@@ -16,7 +16,7 @@
 
 package androidx.ui.text.platform
 
-import android.os.Build
+import androidx.ui.text.PlatformStringDelegate
 
 /**
  * Interface for providing platform dependent locale object.
@@ -64,11 +64,8 @@
     fun parseLanguageTag(languageTag: String): PlatformLocale
 }
 
-private fun createPlatformLocaleDelegate() =
-    if (Build.VERSION.SDK_INT >= 24) {
-        AndroidLocaleDelegateAPI24()
-    } else {
-        AndroidLocaleDelegateAPI23()
-    }
+internal expect fun createPlatformLocaleDelegate(): PlatformLocaleDelegate
 
 internal val platformLocaleDelegate = createPlatformLocaleDelegate()
+
+internal expect fun ActualStringDelegate(): PlatformStringDelegate
diff --git a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt
new file mode 100644
index 0000000..c74f11b
--- /dev/null
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.text.platform
+
+import androidx.ui.text.font.Font
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.Paragraph
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.ParagraphConstraints
+import androidx.ui.text.Placeholder
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.TextStyle
+import androidx.ui.unit.Density
+
+// TODO(b/157854677): remove after fixing.
+internal expect fun ActualParagraph(
+    text: String,
+    style: TextStyle,
+    spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+    placeholders: List<AnnotatedString.Range<Placeholder>>,
+    maxLines: Int,
+    ellipsis: Boolean,
+    constraints: ParagraphConstraints,
+    density: Density,
+    resourceLoader: Font.ResourceLoader
+): Paragraph
+
+// TODO(b/157854677): remove after fixing.
+internal expect fun ActualParagraph(
+    paragraphIntrinsics: ParagraphIntrinsics,
+    maxLines: Int,
+    ellipsis: Boolean,
+    constraints: ParagraphConstraints
+): Paragraph
+
+// TODO(b/157854677): remove after fixing.
+internal expect fun ActualParagraphIntrinsics(
+    text: String,
+    style: TextStyle,
+    spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+    placeholders: List<AnnotatedString.Range<Placeholder>>,
+    density: Density,
+    resourceLoader: Font.ResourceLoader
+): ParagraphIntrinsics
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/BaselineShift.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/BaselineShift.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/BaselineShift.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/BaselineShift.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextAlign.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextAlign.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextAlign.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextAlign.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDecoration.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDecoration.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDecoration.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDecoration.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDirection.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDirection.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDirection.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDirection.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDirectionAlgorithm.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDirectionAlgorithm.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextDirectionAlgorithm.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextDirectionAlgorithm.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextGeometricTransform.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextGeometricTransform.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextGeometricTransform.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextGeometricTransform.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextIndent.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextIndent.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextIndent.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextIndent.kt
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/style/TextOverflow.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextOverflow.kt
similarity index 100%
rename from ui/ui-text-core/src/main/java/androidx/ui/text/style/TextOverflow.kt
rename to ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/style/TextOverflow.kt
diff --git a/ui/ui-text-core/src/jvmMain/kotlin/androidx/ui/text/JvmAnnotatedString.kt b/ui/ui-text-core/src/jvmMain/kotlin/androidx/ui/text/JvmAnnotatedString.kt
new file mode 100644
index 0000000..531a2f7
--- /dev/null
+++ b/ui/ui-text-core/src/jvmMain/kotlin/androidx/ui/text/JvmAnnotatedString.kt
@@ -0,0 +1,78 @@
+/*
+ * 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.text
+
+import androidx.ui.text.AnnotatedString.Range
+
+import java.util.SortedSet
+
+/**
+ * The core function of [AnnotatedString] transformation.
+ *
+ * @param transform the transformation method
+ * @return newly allocated transformed AnnotatedString
+ */
+internal actual fun AnnotatedString.transform(
+    transform: (String, Int, Int) -> String
+): AnnotatedString {
+    val transitions = sortedSetOf(0, text.length)
+    collectRangeTransitions(spanStyles, transitions)
+    collectRangeTransitions(paragraphStyles, transitions)
+
+    var resultStr = ""
+    val offsetMap = mutableMapOf(0 to 0)
+    transitions.windowed(size = 2) { (start, end) ->
+        resultStr += transform(text, start, end)
+        offsetMap.put(end, resultStr.length)
+    }
+
+    val newSpanStyles = spanStyles.map {
+        // The offset map must have mapping entry from all style start, end position.
+        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
+    }
+    val newParaStyles = paragraphStyles.map {
+        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
+    }
+    val newAnnotations = annotations.map {
+        Range(it.item, offsetMap[it.start]!!, offsetMap[it.end]!!)
+    }
+
+    return AnnotatedString(
+        text = resultStr,
+        spanStyles = newSpanStyles,
+        paragraphStyles = newParaStyles,
+        annotations = newAnnotations
+    )
+}
+
+/**
+ * Adds all [AnnotatedString.Range] transition points
+ *
+ * @param ranges The list of AnnotatedString.Range
+ * @param target The output list
+ */
+private fun <T> collectRangeTransitions(
+    ranges: List<Range<T>>,
+    target: SortedSet<Int>
+) {
+    ranges.fold(target) { acc, range ->
+        acc.apply {
+            add(range.start)
+            add(range.end)
+        }
+    }
+}
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/Typeface.kt b/ui/ui-text-core/src/main/java/androidx/ui/text/Typeface.kt
deleted file mode 100644
index d7306ac..0000000
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/Typeface.kt
+++ /dev/null
@@ -1,67 +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.ui.text
-
-import android.content.Context
-import androidx.ui.text.font.DefaultFontFamily
-import androidx.ui.text.font.FontFamily
-import androidx.ui.text.font.FontListFontFamily
-import androidx.ui.text.font.FontStyle
-import androidx.ui.text.font.FontWeight
-import androidx.ui.text.font.GenericFontFamily
-import androidx.ui.text.font.LoadedFontFamily
-import androidx.ui.text.platform.AndroidDefaultTypeface
-import androidx.ui.text.platform.AndroidFontListTypeface
-import androidx.ui.text.platform.AndroidGenericFontFamilyTypeface
-
-/**
- * A class that can be used for changing the font used in text.
- */
-interface Typeface {
-    /**
-     * The font family used for creating this Typeface
-     */
-    val fontFamily: FontFamily
-}
-
-/**
- * Android specific Typeface builder function from FontFamily.
- *
- * You can pass necessaryStyles for loading only specific styles. The font style matching happens
- * only with the loaded Typeface.
- *
- * This function caches the internal native Typeface but always create the new Typeface object.
- * Caller should cache if necessary.
- *
- * @param context the context to be used for loading Typeface.
- * @param fontFamily the font family to be loaded
- * @param necessaryStyles optional style filter for loading subset of fontFamily. null means load
- *                        all fonts in fontFamily.
- * @return A loaded Typeface.
- */
-fun typefaceFromFontFamily(
-    context: Context,
-    fontFamily: FontFamily,
-    necessaryStyles: List<Pair<FontWeight, FontStyle>>? = null
-): Typeface {
-    return when (fontFamily) {
-        is FontListFontFamily -> AndroidFontListTypeface(fontFamily, context, necessaryStyles)
-        is GenericFontFamily -> AndroidGenericFontFamilyTypeface(fontFamily)
-        is DefaultFontFamily -> AndroidDefaultTypeface()
-        is LoadedFontFamily -> fontFamily.typeface
-    }
-}
\ No newline at end of file
diff --git a/ui/ui-text/api/0.1.0-dev14.txt b/ui/ui-text/api/0.1.0-dev14.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/0.1.0-dev14.txt
+++ b/ui/ui-text/api/0.1.0-dev14.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev14.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev14.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/api/restricted_0.1.0-dev14.txt b/ui/ui-text/api/restricted_0.1.0-dev14.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev14.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index c9a485d..360e16b 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -31,7 +31,7 @@
     method public static void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public static void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public static int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public static void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public static void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
     field public static final androidx.ui.text.TextFieldDelegate.Companion! Companion;
   }
 
@@ -42,7 +42,7 @@
     method public void notifyFocusedRect(androidx.ui.input.EditorValue value, androidx.ui.text.TextDelegate textDelegate, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.core.LayoutCoordinates layoutCoordinates, androidx.ui.input.TextInputService textInputService, int token, boolean hasFocus, androidx.ui.input.OffsetMap offsetMap);
     method public void onBlur(androidx.ui.input.TextInputService? textInputService, int token, androidx.ui.input.EditProcessor editProcessor, boolean hasNextClient, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange);
     method public int onFocus(androidx.ui.input.TextInputService? textInputService, androidx.ui.input.EditorValue value, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.KeyboardType keyboardType, androidx.ui.input.ImeAction imeAction, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> onImeActionPerformed);
-    method public void onRelease(androidx.ui.unit.PxPosition position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
+    method public void onRelease(androidx.ui.geometry.Offset position, androidx.ui.text.TextLayoutResult textLayoutResult, androidx.ui.input.EditProcessor editProcessor, androidx.ui.input.OffsetMap offsetMap, kotlin.jvm.functions.Function1<? super androidx.ui.input.EditorValue,kotlin.Unit> onValueChange, androidx.ui.input.TextInputService? textInputService, int token, boolean hasFocus);
   }
 
   public final class TextFieldDelegateKt {
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextFieldDelegateIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextFieldDelegateIntegrationTest.kt
index 5ae9385..71eeaa3 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextFieldDelegateIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextFieldDelegateIntegrationTest.kt
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package androidx.ui.text
 
 import android.content.Context
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutTest.kt
index 784f8c6..c9af8df8 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutTest.kt
@@ -20,7 +20,6 @@
 import androidx.compose.Composable
 import androidx.compose.remember
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Constraints
 import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
@@ -53,8 +52,11 @@
 @RunWith(JUnit4::class)
 @SmallTest
 class TextLayoutTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    internal val activityTestRule = ActivityTestRule(ComponentActivity::class.java)
+    internal val activityTestRule = androidx.test.rule.ActivityTestRule(
+        ComponentActivity::class.java
+    )
     private lateinit var activity: ComponentActivity
     private lateinit var density: Density
 
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/SelectionContainerTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/SelectionContainerTest.kt
index 10af45d..078bfc9 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/SelectionContainerTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/SelectionContainerTest.kt
@@ -42,7 +42,6 @@
 import androidx.ui.text.font.asFontFamily
 import androidx.ui.text.font.test.R
 import androidx.ui.text.style.TextOverflow
-import androidx.ui.unit.px
 import androidx.ui.unit.sp
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.mock
@@ -115,14 +114,14 @@
     fun press_to_cancel() {
         // Setup. Long press to create a selection.
         // A reasonable number.
-        val position = 50.px
-        longPress(x = position.value, y = position.value)
+        val position = 50f
+        longPress(x = position, y = position)
         runOnIdleCompose {
             assertThat(selection.value).isNotNull()
         }
 
         // Act.
-        press(x = position.value, y = position.value)
+        press(x = position, y = position)
 
         // Assert.
         runOnIdleCompose {
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
index da8b09f..ec4a427 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
@@ -42,7 +42,7 @@
 import androidx.ui.text.font.test.R
 import androidx.ui.text.style.TextDirection
 import androidx.ui.unit.Density
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.TextUnit
 import androidx.ui.unit.sp
 import com.google.common.truth.Truth.assertThat
@@ -122,7 +122,7 @@
                 )
 
                 // Assert.
-                assertThat(coordinates).isEqualTo(PxPosition.Origin)
+                assertThat(coordinates).isEqualTo(Offset.Zero)
             }
         }
     }
@@ -179,7 +179,7 @@
                 )
 
                 // Assert.
-                assertThat(coordinates).isEqualTo(PxPosition.Origin)
+                assertThat(coordinates).isEqualTo(Offset.Zero)
             }
         }
     }
@@ -232,7 +232,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * startOffset), fontSizeInPx)
+                    Offset((fontSizeInPx * startOffset), fontSizeInPx)
                 )
             }
         }
@@ -286,7 +286,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * startOffset), fontSizeInPx)
+                    Offset((fontSizeInPx * startOffset), fontSizeInPx)
                 )
             }
         }
@@ -340,7 +340,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length - 1 - startOffset)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length - 1 - startOffset)), fontSizeInPx)
                 )
             }
         }
@@ -394,7 +394,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length - 1 - startOffset)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length - 1 - startOffset)), fontSizeInPx)
                 )
             }
         }
@@ -450,7 +450,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length)), fontSizeInPx)
                 )
             }
         }
@@ -506,7 +506,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (textLtr.length)), fontSizeInPx)
+                    Offset((fontSizeInPx * (textLtr.length)), fontSizeInPx)
                 )
             }
         }
@@ -560,7 +560,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * endOffset), fontSizeInPx)
+                    Offset((fontSizeInPx * endOffset), fontSizeInPx)
                 )
             }
         }
@@ -614,7 +614,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * endOffset), fontSizeInPx)
+                    Offset((fontSizeInPx * endOffset), fontSizeInPx)
                 )
             }
         }
@@ -668,7 +668,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length - 1 - endOffset)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length - 1 - endOffset)), fontSizeInPx)
                 )
             }
         }
@@ -722,7 +722,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length - 1 - endOffset)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length - 1 - endOffset)), fontSizeInPx)
                 )
             }
         }
@@ -778,7 +778,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (textLtr.length)), fontSizeInPx)
+                    Offset((fontSizeInPx * (textLtr.length)), fontSizeInPx)
                 )
             }
         }
@@ -834,7 +834,7 @@
 
                 // Assert.
                 assertThat(coordinates).isEqualTo(
-                    PxPosition((fontSizeInPx * (text.length)), fontSizeInPx)
+                    Offset((fontSizeInPx * (text.length)), fontSizeInPx)
                 )
             }
         }
@@ -1009,7 +1009,7 @@
             density = defaultDensity
         )
 
-        val start = PxPosition((fontSizeInPx * 2), (fontSizeInPx / 2))
+        val start = Offset((fontSizeInPx * 2), (fontSizeInPx / 2))
         val end = start
 
         // Act.
@@ -1048,7 +1048,7 @@
             density = defaultDensity
         )
 
-        val start = PxPosition((fontSizeInPx * 2), (fontSizeInPx / 2))
+        val start = Offset((fontSizeInPx * 2), (fontSizeInPx / 2))
         val end = start
 
         // Act.
@@ -1089,8 +1089,8 @@
 
         val rawStartOffset = text.indexOf('e')
         val rawEndOffset = text.indexOf('r')
-        val start = PxPosition((fontSizeInPx * rawStartOffset), (fontSizeInPx / 2))
-        val end = PxPosition((fontSizeInPx * rawEndOffset), (fontSizeInPx / 2))
+        val start = Offset((fontSizeInPx * rawStartOffset), (fontSizeInPx / 2))
+        val end = Offset((fontSizeInPx * rawEndOffset), (fontSizeInPx / 2))
 
         // Act.
         val textSelectionInfo = getTextSelectionInfo(
@@ -1132,8 +1132,8 @@
 
             val rawStartOffset = text.indexOf('r')
             val rawEndOffset = text.indexOf('e')
-            val start = PxPosition((fontSizeInPx * rawStartOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * rawEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * rawStartOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * rawEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1177,8 +1177,8 @@
             // "llo wor" is selected.
             val startOffset = text.indexOf("l")
             val endOffset = text.indexOf("r") + 1
-            val start = PxPosition((fontSizeInPx * startOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * endOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * startOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * endOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1221,11 +1221,11 @@
             // "\u05D1\u05D2 \u05D3" is selected.
             val startOffset = text.indexOf("\u05D1")
             val endOffset = text.indexOf("\u05D3") + 1
-            val start = PxPosition(
+            val start = Offset(
                 (fontSizeInPx * (text.length - 1 - startOffset)),
                 (fontSizeInPx / 2)
             )
-            val end = PxPosition(
+            val end = Offset(
                 (fontSizeInPx * (text.length - 1 - endOffset)),
                 (fontSizeInPx / 2)
             )
@@ -1273,11 +1273,11 @@
             // "llo"+"\u05D0\u05D1\u05D2" is selected
             val startOffset = text.indexOf("l")
             val endOffset = text.indexOf("\u05D2") + 1
-            val start = PxPosition(
+            val start = Offset(
                 (fontSizeInPx * startOffset),
                 (fontSizeInPx / 2)
             )
-            val end = PxPosition(
+            val end = Offset(
                 (fontSizeInPx * (textLtr.length + text.length - endOffset)),
                 (fontSizeInPx / 2)
             )
@@ -1321,8 +1321,8 @@
             // "llo wor" is selected.
             val startOffset = text.indexOf("r") + 1
             val endOffset = text.indexOf("l")
-            val start = PxPosition((fontSizeInPx * startOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * endOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * startOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * endOffset), (fontSizeInPx / 2))
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
                 selectionCoordinates = Pair(start, end),
@@ -1362,11 +1362,11 @@
             // "\u05D1\u05D2 \u05D3" is selected.
             val startOffset = text.indexOf("\u05D3") + 1
             val endOffset = text.indexOf("\u05D1")
-            val start = PxPosition(
+            val start = Offset(
                 (fontSizeInPx * (text.length - 1 - startOffset)),
                 (fontSizeInPx / 2)
             )
-            val end = PxPosition(
+            val end = Offset(
                 (fontSizeInPx * (text.length - 1 - endOffset)),
                 (fontSizeInPx / 2)
             )
@@ -1412,11 +1412,11 @@
             // "llo"+"\u05D0\u05D1\u05D2" is selected
             val startOffset = text.indexOf("\u05D2") + 1
             val endOffset = text.indexOf("l")
-            val start = PxPosition(
+            val start = Offset(
                 (fontSizeInPx * (textLtr.length + text.length - startOffset)),
                 (fontSizeInPx / 2)
             )
-            val end = PxPosition(
+            val end = Offset(
                 (fontSizeInPx * endOffset),
                 (fontSizeInPx / 2)
             )
@@ -1475,8 +1475,8 @@
                 handlesCrossed = false
             )
             // "l" is selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1531,11 +1531,11 @@
                 handlesCrossed = false
             )
             // "\u05D1" is selected.
-            val start = PxPosition(
+            val start = Offset(
                 (fontSizeInPx * (text.length - 1 - oldStartOffset)),
                 (fontSizeInPx / 2)
             )
-            val end = PxPosition(
+            val end = Offset(
                 (fontSizeInPx * (text.length - 1 - oldStartOffset)),
                 (fontSizeInPx / 2)
             )
@@ -1593,8 +1593,8 @@
                 handlesCrossed = false
             )
             // The Space after "o" is selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1650,8 +1650,8 @@
                 handlesCrossed = true
             )
             // "l" is selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1707,8 +1707,8 @@
                 handlesCrossed = false
             )
             // "e" should be selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1754,8 +1754,8 @@
                 handlesCrossed = true
             )
             // "e" should be selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1801,9 +1801,9 @@
                 handlesCrossed = false
             )
             // "d" should be selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset) - (fontSizeInPx / 2),
+            val start = Offset((fontSizeInPx * oldEndOffset) - (fontSizeInPx / 2),
                 (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset) - 1,
+            val end = Offset((fontSizeInPx * oldEndOffset) - 1,
                 (fontSizeInPx / 2))
 
             // Act.
@@ -1850,8 +1850,8 @@
                 handlesCrossed = true
             )
             // "e" should be selected.
-            val start = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldEndOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1897,8 +1897,8 @@
                 handlesCrossed = true
             )
             // The space after "o" is selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -1954,8 +1954,8 @@
                 handlesCrossed = false
             )
             // "e" should be selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -2001,8 +2001,8 @@
                 handlesCrossed = true
             )
             // "e" should be selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val start = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * oldStartOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -2048,9 +2048,9 @@
                 handlesCrossed = false
             )
             // "h" should be selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset),
+            val start = Offset((fontSizeInPx * oldStartOffset),
                 (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset),
+            val end = Offset((fontSizeInPx * oldStartOffset),
                 (fontSizeInPx / 2))
 
             // Act.
@@ -2097,9 +2097,9 @@
                 handlesCrossed = true
             )
             // "d" should be selected.
-            val start = PxPosition((fontSizeInPx * oldStartOffset) - 1,
+            val start = Offset((fontSizeInPx * oldStartOffset) - 1,
                 (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * oldStartOffset) - 1,
+            val end = Offset((fontSizeInPx * oldStartOffset) - 1,
                 (fontSizeInPx / 2))
 
             // Act.
@@ -2130,8 +2130,8 @@
             )
             // "hello w" is selected.
             val endOffset = text.indexOf("w") + 1
-            val start = PxPosition(-50f, -50f)
-            val end = PxPosition((fontSizeInPx * endOffset), (fontSizeInPx / 2))
+            val start = Offset(-50f, -50f)
+            val end = Offset((fontSizeInPx * endOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -2170,8 +2170,8 @@
             )
             // "o world" is selected.
             val startOffset = text.indexOf("o")
-            val start = PxPosition((fontSizeInPx * startOffset), (fontSizeInPx / 2))
-            val end = PxPosition((fontSizeInPx * text.length * 2), (fontSizeInPx * 2)
+            val start = Offset((fontSizeInPx * startOffset), (fontSizeInPx / 2))
+            val end = Offset((fontSizeInPx * text.length * 2), (fontSizeInPx * 2)
                 )
 
             // Act.
@@ -2212,8 +2212,8 @@
             // "world" is selected.
             val endOffset = text.indexOf("w")
             val start =
-                PxPosition((fontSizeInPx * text.length * 2), (fontSizeInPx * 2))
-            val end = PxPosition((fontSizeInPx * endOffset), (fontSizeInPx / 2))
+                Offset((fontSizeInPx * text.length * 2), (fontSizeInPx * 2))
+            val end = Offset((fontSizeInPx * endOffset), (fontSizeInPx / 2))
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -2254,8 +2254,8 @@
             // "hell" is selected.
             val startOffset = text.indexOf("o")
             val start =
-                PxPosition((fontSizeInPx * startOffset), (fontSizeInPx / 2))
-            val end = PxPosition(-50f, -50f)
+                Offset((fontSizeInPx * startOffset), (fontSizeInPx / 2))
+            val end = Offset(-50f, -50f)
 
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
@@ -2292,8 +2292,8 @@
                 fontSize = fontSize,
                 density = defaultDensity
             )
-            val start = PxPosition(-50f, -50f)
-            val end = PxPosition(-20f, -20f)
+            val start = Offset(-50f, -50f)
+            val end = Offset(-20f, -20f)
             // Act.
             val textSelectionInfo = getTextSelectionInfo(
                 selectionCoordinates = Pair(start, end),
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt b/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
index d5e5ccf..c01ff02 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("DEPRECATION_ERROR")
 package androidx.ui.text
 
 import androidx.compose.Composable
@@ -43,7 +44,7 @@
 import androidx.ui.text.style.TextOverflow
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import androidx.ui.unit.max
 import androidx.ui.unit.min
@@ -208,7 +209,7 @@
                             maxHeight = floor(it.height).toInt().ipx
                         )
                     ),
-                    PxPosition(it.left, it.top)
+                    Offset(it.left, it.top)
                 )
             }
         }
@@ -298,7 +299,7 @@
     /** The latest TextLayoutResult calculated in the measure block */
     var layoutResult: TextLayoutResult? = null
     /** The global position calculated during the last onPositioned callback */
-    var previousGlobalPosition: PxPosition = PxPosition.Origin
+    var previousGlobalPosition: Offset = Offset.Zero
     /** The paint used to draw highlight background for selected text. */
     val selectionPaint: Paint = Paint().apply {
         isAntiAlias = true
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
index 1163973..6ea0dab 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("DEPRECATION_ERROR")
 package androidx.ui.text
 
 import androidx.compose.Composable
@@ -47,7 +48,7 @@
 import androidx.ui.input.VisualTransformation
 import androidx.ui.semantics.Semantics
 import androidx.ui.semantics.onClick
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import kotlin.math.roundToInt
 
@@ -268,8 +269,8 @@
  */
 @Composable
 private fun TextInputEventObserver(
-    onPress: (PxPosition) -> Unit,
-    onRelease: (PxPosition) -> Unit,
+    onPress: (Offset) -> Unit,
+    onRelease: (Offset) -> Unit,
     onFocus: () -> Unit,
     onBlur: (hasNextClient: Boolean) -> Unit,
     focusModifier: FocusModifier,
@@ -332,15 +333,15 @@
  * Helper class for tracking dragging event.
  */
 internal class DragEventTracker {
-    private var origin = PxPosition.Origin
-    private var distance = PxPosition.Origin
+    private var origin = Offset.Zero
+    private var distance = Offset.Zero
 
     /**
      * Restart the tracking from given origin.
      *
      * @param origin The origin of the drag gesture.
      */
-    fun init(origin: PxPosition) {
+    fun init(origin: Offset) {
         this.origin = origin
     }
 
@@ -349,7 +350,7 @@
      *
      * @param distance The distance from the origin of the drag origin.
      */
-    fun onDrag(distance: PxPosition) {
+    fun onDrag(distance: Offset) {
         this.distance = distance
     }
 
@@ -358,7 +359,7 @@
      *
      * @return The position of the current drag point.
      */
-    fun getPosition(): PxPosition {
+    fun getPosition(): Offset {
         return origin + distance
     }
 }
@@ -368,8 +369,8 @@
  */
 @Composable
 private fun Modifier.dragPositionGestureFilter(
-    onPress: (PxPosition) -> Unit,
-    onRelease: (PxPosition) -> Unit
+    onPress: (Offset) -> Unit,
+    onRelease: (Offset) -> Unit
 ): Modifier {
     val tracker = state { DragEventTracker() }
     // TODO(shepshapard): PressIndicator doesn't seem to be the right thing to use here.  It
@@ -386,9 +387,9 @@
             })
         .dragGestureFilter(dragObserver = object :
             DragObserver {
-            override fun onDrag(dragDistance: PxPosition): PxPosition {
+            override fun onDrag(dragDistance: Offset): Offset {
                 tracker.value.onDrag(dragDistance)
-                return PxPosition.Origin
+                return Offset.Zero
             }
         })
 }
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/TextFieldDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/TextFieldDelegate.kt
index e480ac7..997e5dc 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/TextFieldDelegate.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/TextFieldDelegate.kt
@@ -40,7 +40,7 @@
 import androidx.ui.text.style.TextDirectionAlgorithm
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPx
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
 import kotlin.math.ceil
 import kotlin.math.roundToInt
@@ -182,7 +182,7 @@
                 )
                 Rect(0f, 0f, 1.0f, lineHeightForEmptyText.value.toFloat())
             }
-            val globalLT = layoutCoordinates.localToRoot(PxPosition(bbox.left, bbox.top))
+            val globalLT = layoutCoordinates.localToRoot(Offset(bbox.left, bbox.top))
 
             textInputService.notifyFocusedRect(
                 token,
@@ -225,7 +225,7 @@
          */
         @JvmStatic
         fun onRelease(
-            position: PxPosition,
+            position: Offset,
             textLayoutResult: TextLayoutResult,
             editProcessor: EditProcessor,
             offsetMap: OffsetMap,
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/SelectionMode.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/SelectionMode.kt
index 11a5626..a29172f 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/selection/SelectionMode.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/SelectionMode.kt
@@ -17,7 +17,7 @@
 package androidx.ui.text.selection
 
 import androidx.ui.geometry.Rect
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 
 /**
  * The enum class allows user to decide the selection mode.
@@ -31,8 +31,8 @@
     Vertical {
         override fun isSelected(
             bounds: Rect,
-            start: PxPosition,
-            end: PxPosition
+            start: Offset,
+            end: Offset
         ): Boolean {
             // When the end of the selection is above the top of the composable, the composable is outside
             // of the selection range.
@@ -55,8 +55,8 @@
 
         override fun areHandlesCrossed(
             bounds: Rect,
-            start: PxPosition,
-            end: PxPosition
+            start: Offset,
+            end: Offset
         ): Boolean {
             if (start.y >= bounds.top && start.y < bounds.bottom &&
                 end.y >= bounds.top && end.y < bounds.bottom
@@ -80,8 +80,8 @@
     Horizontal {
         override fun isSelected(
             bounds: Rect,
-            start: PxPosition,
-            end: PxPosition
+            start: Offset,
+            end: Offset
         ): Boolean {
             // When the end of the selection is on the left of the composable, the composable is outside of
             // the selection range.
@@ -104,8 +104,8 @@
 
         override fun areHandlesCrossed(
             bounds: Rect,
-            start: PxPosition,
-            end: PxPosition
+            start: Offset,
+            end: Offset
         ): Boolean {
             if (start.x >= bounds.left && start.x < bounds.right &&
                 end.x >= bounds.left && end.x < bounds.right
@@ -131,8 +131,8 @@
      */
     internal abstract fun isSelected(
         bounds: Rect,
-        start: PxPosition,
-        end: PxPosition
+        start: Offset,
+        end: Offset
     ): Boolean
 
     /**
@@ -146,7 +146,7 @@
      */
     internal abstract fun areHandlesCrossed(
         bounds: Rect,
-        start: PxPosition,
-        end: PxPosition
+        start: Offset,
+        end: Offset
     ): Boolean
 }
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
index b944012..49d5857 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
@@ -19,13 +19,11 @@
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.selection.Selectable
 import androidx.ui.core.selection.Selection
-import androidx.ui.geometry.Offset
 import androidx.ui.geometry.Rect
 import androidx.ui.text.AnnotatedString
 import androidx.ui.text.TextLayoutResult
 import androidx.ui.text.TextRange
-import androidx.ui.unit.PxPosition
-import androidx.ui.unit.toPx
+import androidx.ui.geometry.Offset
 import kotlin.math.max
 
 internal class TextSelectionDelegate(
@@ -34,8 +32,8 @@
     private val layoutResultCallback: () -> TextLayoutResult?
 ) : Selectable {
     override fun getSelection(
-        startPosition: PxPosition,
-        endPosition: PxPosition,
+        startPosition: Offset,
+        endPosition: Offset,
         containerLayoutCoordinates: LayoutCoordinates,
         longPress: Boolean,
         previousSelection: Selection?,
@@ -45,7 +43,7 @@
         val textLayoutResult = layoutResultCallback() ?: return null
 
         val relativePosition = containerLayoutCoordinates.childToLocal(
-            layoutCoordinates, PxPosition.Origin
+            layoutCoordinates, Offset.Zero
         )
         val startPx = startPosition - relativePosition
         val endPx = endPosition - relativePosition
@@ -68,16 +66,16 @@
         }
     }
 
-    override fun getHandlePosition(selection: Selection, isStartHandle: Boolean): PxPosition {
+    override fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset {
         // Check if the selection handles's selectable is the current selectable.
         if (isStartHandle && selection.start.selectable != this ||
             !isStartHandle && selection.end.selectable != this) {
-            return PxPosition.Origin
+            return Offset.Zero
         }
 
-        if (getLayoutCoordinates() == null) return PxPosition.Origin
+        if (getLayoutCoordinates() == null) return Offset.Zero
 
-        val textLayoutResult = layoutResultCallback() ?: return PxPosition.Origin
+        val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
         return getSelectionHandleCoordinates(
             textLayoutResult = textLayoutResult,
             offset = if (isStartHandle) selection.start.offset else selection.end.offset,
@@ -126,7 +124,7 @@
  */
 internal fun getTextSelectionInfo(
     textLayoutResult: TextLayoutResult,
-    selectionCoordinates: Pair<PxPosition, PxPosition>,
+    selectionCoordinates: Pair<Offset, Offset>,
     selectable: Selectable,
     wordBasedSelection: Boolean,
     previousSelection: Selection? = null,
@@ -138,8 +136,8 @@
     val bounds = Rect(
         0.0f,
         0.0f,
-        textLayoutResult.size.width.toPx().value,
-        textLayoutResult.size.height.toPx().value
+        textLayoutResult.size.width.value.toFloat(),
+        textLayoutResult.size.height.value.toFloat()
     )
 
     val lastOffset = textLayoutResult.layoutInput.text.text.length
@@ -212,8 +210,8 @@
     rawEndOffset: Int,
     containsWholeSelectionStart: Boolean,
     containsWholeSelectionEnd: Boolean,
-    startPosition: PxPosition,
-    endPosition: PxPosition,
+    startPosition: Offset,
+    endPosition: Offset,
     bounds: Rect,
     textLayoutResult: TextLayoutResult,
     lastOffset: Int,
@@ -366,8 +364,8 @@
  * crossed each other.
  */
 private fun processCrossComposable(
-    startPosition: PxPosition,
-    endPosition: PxPosition,
+    startPosition: Offset,
+    endPosition: Offset,
     rawStartOffset: Int,
     rawEndOffset: Int,
     lastOffset: Int,
@@ -512,7 +510,7 @@
     offset: Int,
     isStart: Boolean,
     areHandlesCrossed: Boolean
-): PxPosition {
+): Offset {
     val line = textLayoutResult.getLineForOffset(offset)
     val offsetToCheck =
         if (isStart && !areHandlesCrossed || !isStart && areHandlesCrossed) offset
@@ -526,5 +524,5 @@
     )
     val y = textLayoutResult.getLineBottom(line)
 
-    return PxPosition(x, y)
+    return Offset(x, y)
 }
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/DragEventTrackerTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/DragEventTrackerTest.kt
index 80cabf9..e1980c0 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/DragEventTrackerTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/DragEventTrackerTest.kt
@@ -16,7 +16,7 @@
 
 package androidx.ui.text
 
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -28,38 +28,38 @@
     fun test_not_moving() {
         val tracker = DragEventTracker()
 
-        tracker.init(PxPosition(10f, 20f))
-        assertEquals(PxPosition(10f, 20f), tracker.getPosition())
+        tracker.init(Offset(10f, 20f))
+        assertEquals(Offset(10f, 20f), tracker.getPosition())
     }
 
     @Test
     fun test_drag_one_distance() {
         val tracker = DragEventTracker()
 
-        tracker.init(PxPosition(10f, 20f))
-        tracker.onDrag(PxPosition(30f, 40f))
-        assertEquals(PxPosition(40f, 60f), tracker.getPosition())
+        tracker.init(Offset(10f, 20f))
+        tracker.onDrag(Offset(30f, 40f))
+        assertEquals(Offset(40f, 60f), tracker.getPosition())
     }
 
     @Test
     fun test_drag_two_distance() {
         val tracker = DragEventTracker()
 
-        tracker.init(PxPosition(10f, 20f))
-        tracker.onDrag(PxPosition(30f, 40f))
-        tracker.onDrag(PxPosition(50f, 60f))
-        assertEquals(PxPosition(60f, 80f), tracker.getPosition())
+        tracker.init(Offset(10f, 20f))
+        tracker.onDrag(Offset(30f, 40f))
+        tracker.onDrag(Offset(50f, 60f))
+        assertEquals(Offset(60f, 80f), tracker.getPosition())
     }
 
     @Test
     fun test_drag_twice() {
         val tracker = DragEventTracker()
 
-        tracker.init(PxPosition(10f, 20f))
-        tracker.onDrag(PxPosition(30f, 40f))
+        tracker.init(Offset(10f, 20f))
+        tracker.onDrag(Offset(30f, 40f))
 
-        tracker.init(PxPosition(50f, 60f))
-        tracker.onDrag(PxPosition(70f, 80f))
-        assertEquals(PxPosition(120f, 140f), tracker.getPosition())
+        tracker.init(Offset(50f, 60f))
+        tracker.onDrag(Offset(70f, 80f))
+        assertEquals(Offset(120f, 140f), tracker.getPosition())
     }
 }
\ No newline at end of file
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/TextFieldDelegateTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/TextFieldDelegateTest.kt
index 606a496..1f28e94 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/TextFieldDelegateTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/TextFieldDelegateTest.kt
@@ -37,10 +37,8 @@
 import androidx.ui.text.style.TextDecoration
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntPxSize
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.ipx
-import androidx.ui.unit.px
-import androidx.ui.unit.round
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.argumentCaptor
@@ -112,7 +110,7 @@
 
     @Test
     fun test_on_release() {
-        val position = PxPosition(100f, 200f)
+        val position = Offset(100f, 200f)
         val offset = 10
         val dummyEditorState = EditorValue(text = "Hello, World", selection = TextRange(1, 1))
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
@@ -147,7 +145,7 @@
 
     @Test
     fun test_on_release_do_not_place_cursor_if_focus_is_out() {
-        val position = PxPosition(100f, 200f)
+        val position = Offset(100f, 200f)
         val offset = 10
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
 
@@ -231,7 +229,7 @@
     fun notify_focused_rect() {
         val dummyRect = Rect(0f, 1f, 2f, 3f)
         whenever(textLayoutResult.getBoundingBox(any())).thenReturn(dummyRect)
-        val dummyPoint = PxPosition(5f, 6f)
+        val dummyPoint = Offset(5f, 6f)
         whenever(layoutCoordinates.localToRoot(any())).thenReturn(dummyPoint)
         val dummyEditorState = EditorValue(text = "Hello, World", selection = TextRange(1, 1))
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
@@ -269,7 +267,7 @@
     fun notify_rect_tail() {
         val dummyRect = Rect(0f, 1f, 2f, 3f)
         whenever(textLayoutResult.getBoundingBox(any())).thenReturn(dummyRect)
-        val dummyPoint = PxPosition(5f, 6f)
+        val dummyPoint = Offset(5f, 6f)
         whenever(layoutCoordinates.localToRoot(any())).thenReturn(dummyPoint)
         val dummyEditorState = EditorValue(text = "Hello, World", selection = TextRange(12, 12))
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
@@ -289,10 +287,10 @@
     @Test
     fun layout() {
         val constraints = Constraints(
-            minWidth = 0.px.round(),
-            maxWidth = 1280.px.round(),
-            minHeight = 0.px.round(),
-            maxHeight = 2048.px.round()
+            minWidth = 0.ipx,
+            maxWidth = 1280.ipx,
+            minHeight = 0.ipx,
+            maxHeight = 2048.ipx
         )
 
         val dummyText = AnnotatedString(text = "Hello, World")
@@ -308,15 +306,15 @@
             constraints,
             layoutDirection
         )
-        assertEquals(1024.px.round(), width)
-        assertEquals(512.px.round(), height)
+        assertEquals(1024f, width.value.toFloat())
+        assertEquals(512f, height.value.toFloat())
         assertEquals(layoutResult, textLayoutResult)
     }
 
     @Test
     fun check_notify_rect_uses_offset_map() {
         val dummyRect = Rect(0f, 1f, 2f, 3f)
-        val dummyPoint = PxPosition(5f, 6f)
+        val dummyPoint = Offset(5f, 6f)
         val dummyEditorState = EditorValue(text = "Hello, World", selection = TextRange(1, 3))
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
         whenever(textLayoutResult.getBoundingBox(any())).thenReturn(dummyRect)
@@ -338,7 +336,7 @@
 
     @Test
     fun check_on_release_uses_offset_map() {
-        val position = PxPosition(100f, 200f)
+        val position = Offset(100f, 200f)
         val offset = 10
         val dummyEditorState = EditorValue(text = "Hello, World", selection = TextRange(1, 1))
         val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/selection/SelectionModeTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/selection/SelectionModeTest.kt
index f015172..93c6389 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/selection/SelectionModeTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/selection/SelectionModeTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.ui.geometry.Rect
-import androidx.ui.unit.PxPosition
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -46,8 +46,8 @@
 
     @Test
     fun isSelected_Vertical_contains_start_return_true() {
-        val start = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -56,8 +56,8 @@
 
     @Test
     fun isSelected_Vertical_contains_end_return_true() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -66,8 +66,8 @@
 
     @Test
     fun isSelected_Vertical_contains_start_and_end_return_true() {
-        val start = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val start = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val end = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -76,8 +76,8 @@
 
     @Test
     fun isSelected_Vertical_smaller_than_top_return_false() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = largerThanRight, y = smallerThanTop)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = largerThanRight, y = smallerThanTop)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -86,8 +86,8 @@
 
     @Test
     fun isSelected_Vertical_larger_than_bottom_return_false() {
-        val start = PxPosition(x = smallerThanLeft, y = largerThanBottom)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = smallerThanLeft, y = largerThanBottom)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -96,8 +96,8 @@
 
     @Test
     fun isSelected_Vertical_same_row_smaller_than_left_return_false() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = smallerThanLeft, y = betweenTopAndBottom)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = smallerThanLeft, y = betweenTopAndBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -106,8 +106,8 @@
 
     @Test
     fun isSelected_Vertical_same_row_larger_than_right_return_false() {
-        val start = PxPosition(x = largerThanRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = largerThanRight, y = betweenTopAndBottom)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Vertical.isSelected(bounds = bounds, start = start, end = end)
 
@@ -116,8 +116,8 @@
 
     @Test
     fun isSelected_Horizontal_contains_start_return_true() {
-        val start = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -126,8 +126,8 @@
 
     @Test
     fun isSelected_Horizontal_contains_end_return_true() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -136,8 +136,8 @@
 
     @Test
     fun isSelected_Horizontal_contains_start_and_end_return_true() {
-        val start = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val start = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
+        val end = Offset(x = betweenLeftAndRight, y = betweenTopAndBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -146,8 +146,8 @@
 
     @Test
     fun isSelected_Horizontal_smaller_than_left_return_false() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = smallerThanLeft, y = largerThanBottom)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = smallerThanLeft, y = largerThanBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -156,8 +156,8 @@
 
     @Test
     fun isSelected_Horizontal_larger_than_right_return_false() {
-        val start = PxPosition(x = largerThanRight, y = smallerThanTop)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = largerThanRight, y = smallerThanTop)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -166,8 +166,8 @@
 
     @Test
     fun isSelected_Horizontal_same_column_smaller_than_top_return_false() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = betweenLeftAndRight, y = smallerThanTop)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = betweenLeftAndRight, y = smallerThanTop)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -176,8 +176,8 @@
 
     @Test
     fun isSelected_Horizontal_same_column_larger_than_bottom_return_false() {
-        val start = PxPosition(x = betweenLeftAndRight, y = largerThanBottom)
-        val end = PxPosition(x = largerThanRight, y = largerThanBottom)
+        val start = Offset(x = betweenLeftAndRight, y = largerThanBottom)
+        val end = Offset(x = largerThanRight, y = largerThanBottom)
 
         val result = SelectionMode.Horizontal.isSelected(bounds = bounds, start = start, end = end)
 
@@ -186,8 +186,8 @@
 
     @Test
     fun areHandlesCrossed_Vertical_same_row_not_crossed() {
-        val start = PxPosition(x = smallerThanLeft, y = betweenTopAndBottom)
-        val end = PxPosition(x = largerThanRight, y = betweenTopAndBottom)
+        val start = Offset(x = smallerThanLeft, y = betweenTopAndBottom)
+        val end = Offset(x = largerThanRight, y = betweenTopAndBottom)
 
         val result =
             SelectionMode.Vertical.areHandlesCrossed(
@@ -200,8 +200,8 @@
 
     @Test
     fun areHandlesCrossed_Vertical_same_row_crossed() {
-        val start = PxPosition(x = largerThanRight, y = betweenTopAndBottom)
-        val end = PxPosition(x = smallerThanLeft, y = betweenTopAndBottom)
+        val start = Offset(x = largerThanRight, y = betweenTopAndBottom)
+        val end = Offset(x = smallerThanLeft, y = betweenTopAndBottom)
 
         val result =
             SelectionMode.Vertical.areHandlesCrossed(
@@ -214,8 +214,8 @@
 
     @Test
     fun areHandlesCrossed_Vertical_different_rows_not_crossed() {
-        val start = PxPosition(x = smallerThanLeft, y = smallerThanTop)
-        val end = PxPosition(x = smallerThanLeft, y = largerThanBottom)
+        val start = Offset(x = smallerThanLeft, y = smallerThanTop)
+        val end = Offset(x = smallerThanLeft, y = largerThanBottom)
 
         val result =
             SelectionMode.Vertical.areHandlesCrossed(
@@ -228,8 +228,8 @@
 
     @Test
     fun areHandlesCrossed_Vertical_different_rows_crossed() {
-        val start = PxPosition(x = smallerThanLeft, y = largerThanBottom)
-        val end = PxPosition(x = largerThanRight, y = smallerThanTop)
+        val start = Offset(x = smallerThanLeft, y = largerThanBottom)
+        val end = Offset(x = largerThanRight, y = smallerThanTop)
 
         val result =
             SelectionMode.Vertical.areHandlesCrossed(
@@ -242,8 +242,8 @@
 
     @Test
     fun areHandlesCrossed_Horizontal_same_column_not_crossed() {
-        val start = PxPosition(x = betweenLeftAndRight, y = smallerThanTop)
-        val end = PxPosition(x = betweenLeftAndRight, y = largerThanBottom)
+        val start = Offset(x = betweenLeftAndRight, y = smallerThanTop)
+        val end = Offset(x = betweenLeftAndRight, y = largerThanBottom)
 
         val result =
             SelectionMode.Horizontal.areHandlesCrossed(
@@ -256,8 +256,8 @@
 
     @Test
     fun areHandlesCrossed_Horizontal_same_column_crossed() {
-        val start = PxPosition(x = betweenLeftAndRight, y = largerThanBottom)
-        val end = PxPosition(x = betweenLeftAndRight, y = smallerThanTop)
+        val start = Offset(x = betweenLeftAndRight, y = largerThanBottom)
+        val end = Offset(x = betweenLeftAndRight, y = smallerThanTop)
 
         val result =
             SelectionMode.Horizontal.areHandlesCrossed(
@@ -270,8 +270,8 @@
 
     @Test
     fun areHandlesCrossed_Horizontal_different_columns_not_crossed() {
-        val start = PxPosition(x = smallerThanLeft, y = largerThanBottom)
-        val end = PxPosition(x = largerThanRight, y = smallerThanTop)
+        val start = Offset(x = smallerThanLeft, y = largerThanBottom)
+        val end = Offset(x = largerThanRight, y = smallerThanTop)
 
         val result =
             SelectionMode.Horizontal.areHandlesCrossed(
@@ -284,8 +284,8 @@
 
     @Test
     fun areHandlesCrossed_Horizontal_different_columns_crossed() {
-        val start = PxPosition(x = largerThanRight, y = smallerThanTop)
-        val end = PxPosition(x = smallerThanLeft, y = largerThanBottom)
+        val start = Offset(x = largerThanRight, y = smallerThanTop)
+        val end = Offset(x = smallerThanLeft, y = largerThanBottom)
 
         val result =
             SelectionMode.Horizontal.areHandlesCrossed(
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ComposeViewAdapterTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ComposeViewAdapterTest.kt
index 888710b..fa94958 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ComposeViewAdapterTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ComposeViewAdapterTest.kt
@@ -18,7 +18,6 @@
 
 import android.os.Bundle
 import androidx.activity.ComponentActivity
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.tooling.preview.ComposeViewAdapter
 import androidx.ui.tooling.preview.ViewInfo
 import androidx.ui.tooling.test.R
@@ -30,8 +29,11 @@
 import org.junit.Test
 
 class ComposeViewAdapterTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
 
     private lateinit var composeViewAdapter: ComposeViewAdapter
 
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/PreviewActivityTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/PreviewActivityTest.kt
index 5d653eb..713c203 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/PreviewActivityTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/PreviewActivityTest.kt
@@ -18,7 +18,6 @@
 
 import android.content.Intent
 import android.view.ViewGroup
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.tooling.preview.PreviewActivity
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -26,8 +25,9 @@
 import org.junit.Test
 
 class PreviewActivityTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule(PreviewActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule(PreviewActivity::class.java)
 
     private lateinit var intent: Intent
 
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 4c9fdc3..5aa241a 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
@@ -18,7 +18,6 @@
 
 import android.os.Handler
 import androidx.compose.Composable
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.core.Modifier
 import androidx.ui.core.onPositioned
 import androidx.ui.core.setContent
@@ -30,8 +29,9 @@
 import java.util.concurrent.TimeUnit
 
 open class ToolingTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
         TestActivity::class.java
     )
     lateinit var activity: TestActivity
@@ -67,7 +67,8 @@
 
 // Kotlin IR compiler doesn't seem too happy with auto-conversion from
 // lambda to Runnable, so separate it here
-fun ActivityTestRule<TestActivity>.onUiThread(block: () -> Unit) {
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<TestActivity>.onUiThread(block: () -> Unit) {
     val runnable: Runnable = object : Runnable {
         override fun run() {
             block()
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/PreviewParameterTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/PreviewParameterTest.kt
index 4bf53bf..218d5f1 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/PreviewParameterTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/PreviewParameterTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.ui.tooling.preview
 
-import androidx.test.rule.ActivityTestRule
 import androidx.ui.material.ColorPalette
 import androidx.ui.material.darkColorPalette
 import androidx.ui.material.lightColorPalette
@@ -30,8 +29,10 @@
 import org.junit.Test
 
 class PreviewParameterTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<ComposeViewAdapterTest.Companion.TestActivity>(
+    val activityTestRule =
+        androidx.test.rule.ActivityTestRule<ComposeViewAdapterTest.Companion.TestActivity>(
         ComposeViewAdapterTest.Companion.TestActivity::class.java
     )
 
diff --git a/ui/ui-unit/api/0.1.0-dev14.txt b/ui/ui-unit/api/0.1.0-dev14.txt
index 14182cc..6e1d7fe 100644
--- a/ui/ui-unit/api/0.1.0-dev14.txt
+++ b/ui/ui-unit/api/0.1.0-dev14.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -350,13 +346,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -425,40 +421,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -477,8 +439,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -503,71 +463,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
     method @androidx.compose.Stable public inline operator androidx.ui.unit.PxSize div(int other);
@@ -595,7 +513,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -605,7 +522,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -694,10 +610,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/api/current.txt b/ui/ui-unit/api/current.txt
index 14182cc..6e1d7fe 100644
--- a/ui/ui-unit/api/current.txt
+++ b/ui/ui-unit/api/current.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -350,13 +346,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -425,40 +421,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -477,8 +439,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -503,71 +463,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
     method @androidx.compose.Stable public inline operator androidx.ui.unit.PxSize div(int other);
@@ -595,7 +513,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -605,7 +522,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -694,10 +610,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev14.txt
index 14182cc..6e1d7fe 100644
--- a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev14.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -350,13 +346,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -425,40 +421,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -477,8 +439,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -503,71 +463,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
     method @androidx.compose.Stable public inline operator androidx.ui.unit.PxSize div(int other);
@@ -595,7 +513,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -605,7 +522,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -694,10 +610,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/api/public_plus_experimental_current.txt b/ui/ui-unit/api/public_plus_experimental_current.txt
index 14182cc..6e1d7fe 100644
--- a/ui/ui-unit/api/public_plus_experimental_current.txt
+++ b/ui/ui-unit/api/public_plus_experimental_current.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -350,13 +346,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -425,40 +421,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -477,8 +439,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -503,71 +463,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
     method @androidx.compose.Stable public inline operator androidx.ui.unit.PxSize div(int other);
@@ -595,7 +513,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -605,7 +522,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -694,10 +610,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/api/restricted_0.1.0-dev14.txt b/ui/ui-unit/api/restricted_0.1.0-dev14.txt
index cd7cfe1..c31949b 100644
--- a/ui/ui-unit/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-unit/api/restricted_0.1.0-dev14.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -352,13 +348,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -429,40 +425,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -481,8 +443,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -507,72 +467,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    ctor @kotlin.PublishedApi internal PxPosition(internal long value);
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     ctor @kotlin.PublishedApi internal PxSize(internal long value);
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
@@ -601,7 +518,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -611,7 +527,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -704,10 +619,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/api/restricted_current.txt b/ui/ui-unit/api/restricted_current.txt
index cd7cfe1..c31949b 100644
--- a/ui/ui-unit/api/restricted_current.txt
+++ b/ui/ui-unit/api/restricted_current.txt
@@ -97,7 +97,6 @@
     method public float getFontScale();
     method @androidx.compose.Stable public default float toDp(float);
     method @androidx.compose.Stable public default float toDp(int);
-    method @androidx.compose.Stable public default float toDp-NgWp0Z8(float);
     method @androidx.compose.Stable public default float toDp-gshw56o(int);
     method @androidx.compose.Stable public default float toDp-vVlMl6k(long);
     method @androidx.compose.Stable public default int toIntPx-ipo6vVg(float);
@@ -107,7 +106,6 @@
     method @androidx.compose.Stable public default androidx.ui.geometry.Rect toRect(androidx.ui.unit.Bounds);
     method @androidx.compose.Stable public default long toSp(float);
     method @androidx.compose.Stable public default long toSp(int);
-    method @androidx.compose.Stable public default long toSp-NgWp0Z8(float);
     method @androidx.compose.Stable public default long toSp-gshw56o(int);
     method @androidx.compose.Stable public default long toSp-ipo6vVg(float);
     property public abstract float density;
@@ -290,7 +288,6 @@
 
   @androidx.compose.Immutable public final inline class IntPx implements java.lang.Comparable<androidx.ui.unit.IntPx> {
     ctor public IntPx();
-    method @androidx.compose.Stable public static inline operator int compareTo-NgWp0Z8(int $this, float other);
     method @androidx.compose.Stable public operator int compareTo-gshw56o(int p);
     method @androidx.compose.Stable public static operator int compareTo-gshw56o(int $this, int other);
     method public static int constructor-impl(int value);
@@ -334,9 +331,8 @@
   public final class IntPxKt {
     method public static inline androidx.ui.unit.IntPxPosition IntPxPosition-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize IntPxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition-rRMsBxU(int x, int y);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset Offset-rRMsBxU(int x, int y);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-rRMsBxU(int width, int height);
-    method @androidx.compose.Stable public static inline int ceil-NgWp0Z8(float);
     method @androidx.compose.Stable public static androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition center(androidx.ui.unit.IntPxBounds);
     method @androidx.compose.Stable public static inline int coerceAtLeast-rRMsBxU(int, int minimumValue);
@@ -352,13 +348,13 @@
     method @androidx.compose.Stable public static int lerp-9BbVZj8(int start, int stop, float fraction);
     method @androidx.compose.Stable public static inline int max-rRMsBxU(int a, int b);
     method @androidx.compose.Stable public static inline int min-rRMsBxU(int a, int b);
-    method @androidx.compose.Stable public static inline int round-NgWp0Z8(float);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset minus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
+    method @androidx.compose.Stable public static inline operator androidx.ui.geometry.Offset plus(androidx.ui.geometry.Offset, androidx.ui.unit.IntPxPosition other);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.IntPxSize times(int, androidx.ui.unit.IntPxSize size);
     method @androidx.compose.Stable public static inline operator int times--Vi_IPY(float, int other);
     method @androidx.compose.Stable public static inline operator int times-9kGzznM(int, int other);
     method @androidx.compose.Stable public static inline operator int times-tHVXE4c(double, int other);
-    method public static inline float toPx-gshw56o(int);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition toPxPosition(androidx.ui.unit.IntPxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset toOffset(androidx.ui.unit.IntPxPosition);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize toPxSize(androidx.ui.unit.IntPxSize);
     method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxSize toSize(androidx.ui.unit.IntPxBounds);
   }
@@ -429,40 +425,6 @@
     method @androidx.compose.Stable public static String toString-impl(long $this);
   }
 
-  @androidx.compose.Immutable public final inline class Px implements java.lang.Comparable<androidx.ui.unit.Px> {
-    ctor public Px();
-    method @androidx.compose.Stable public operator int compareTo-NgWp0Z8(float p);
-    method @androidx.compose.Stable public static operator int compareTo-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator int compareTo-gshw56o(float $this, int other);
-    method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-impl(float $this, int other);
-    method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
-    method public static boolean equals-impl0(float p1, float p2);
-    method public float getValue();
-    method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
-    method @androidx.compose.Stable public static inline operator float minus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float minus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float plus-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float plus-gshw56o(float $this, int other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-impl(float $this, int other);
-    method @androidx.compose.Stable public static String toString-impl(float $this);
-    method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
-    field public static final androidx.ui.unit.Px.Companion! Companion;
-  }
-
-  public static final class Px.Companion {
-    method public float getInfinity();
-    method public float getZero();
-    property public final float Infinity;
-    property public final float Zero;
-  }
-
   @androidx.compose.Immutable public final class PxBounds {
     ctor public PxBounds(float left, float top, float right, float bottom);
     method public float component1();
@@ -481,8 +443,6 @@
     method @androidx.compose.Stable public operator int compareTo-bji3ab4(float p);
     method @androidx.compose.Stable public static operator int compareTo-bji3ab4(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
     method @androidx.compose.Immutable public static inline boolean equals-impl(float p, Object? p1);
@@ -507,72 +467,29 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-KGV0gLo(float $this, float dimension);
     method @androidx.compose.Stable public static inline operator float plus-KGV0gLo(float $this, float dimension);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
 
   public final class PxKt {
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.unit.PxPosition topLeft, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition PxPosition(float x, float y);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.PxBounds PxBounds(androidx.ui.geometry.Offset topLeft, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize(float width, float height);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxSize PxSize-qHcltEY(float width, float height);
-    method @androidx.compose.Stable public static inline float abs-NgWp0Z8(float x);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition center(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.PxPosition center(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static inline float coerceAtLeast-qHcltEY(float, float minimumValue);
-    method @androidx.compose.Stable public static inline float coerceAtMost-qHcltEY(float, float maximumValue);
-    method @androidx.compose.Stable public static inline float coerceIn-HXvnt1Q(float, float minimumValue, float maximumValue);
-    method @androidx.compose.Stable public static inline operator float div-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float div-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float div-kxDXtn8(float, float other);
-    method @androidx.compose.Stable public static float getDistance(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static androidx.ui.geometry.Offset center(androidx.ui.unit.PxSize);
+    method @androidx.compose.Stable public static inline androidx.ui.geometry.Offset center(androidx.ui.unit.PxBounds);
     method public static inline float getHeight(androidx.ui.unit.PxBounds);
     method public static float getMinDimension(androidx.ui.unit.PxSize);
-    method public static inline float getPx(int);
-    method public static inline float getPx(double);
-    method public static inline float getPx(float);
     method public static inline float getWidth(androidx.ui.unit.PxBounds);
-    method @androidx.compose.Stable public static androidx.ui.unit.PxPosition lerp(androidx.ui.unit.PxPosition start, androidx.ui.unit.PxPosition stop, float fraction);
-    method @androidx.compose.Stable public static float lerp-g-Fs4Ag(float start, float stop, float fraction);
-    method @androidx.compose.Stable public static inline float max-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline float min-qHcltEY(float a, float b);
-    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.unit.PxPosition);
+    method @androidx.compose.Stable public static inline androidx.ui.unit.IntPxPosition round(androidx.ui.geometry.Offset);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(int, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(float, androidx.ui.unit.PxSize size);
     method @androidx.compose.Stable public static inline operator androidx.ui.unit.PxSize times(double, androidx.ui.unit.PxSize size);
-    method @androidx.compose.Stable public static inline operator float times-78fIwVY(double, float other);
-    method @androidx.compose.Stable public static inline operator float times-Ndu7NvY(int, float other);
-    method @androidx.compose.Stable public static inline operator float times-kxDXtn8(float, float other);
     method @androidx.compose.Stable public static androidx.ui.unit.PxBounds toBounds(androidx.ui.unit.PxSize);
-    method @androidx.compose.Stable public static inline long toOffset(androidx.ui.unit.PxPosition);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxBounds);
     method @androidx.compose.Stable public static androidx.ui.geometry.Rect toRect(androidx.ui.unit.PxSize);
     method @androidx.compose.Stable public static androidx.ui.unit.PxSize toSize(androidx.ui.unit.PxBounds);
   }
 
-  @androidx.compose.Immutable public final class PxPosition {
-    ctor @kotlin.PublishedApi internal PxPosition(internal long value);
-    method @androidx.compose.Immutable public androidx.ui.unit.PxPosition copy(long value);
-    method public inline float getX();
-    method public inline float getY();
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition minus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.PxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition plus(androidx.ui.unit.IntPxPosition other);
-    method @androidx.compose.Stable public inline operator androidx.ui.unit.PxPosition unaryMinus();
-    property public final inline float x;
-    property public final inline float y;
-    field public static final androidx.ui.unit.PxPosition.Companion! Companion;
-  }
-
-  public static final class PxPosition.Companion {
-    method public androidx.ui.unit.PxPosition getOrigin();
-    property public final androidx.ui.unit.PxPosition Origin;
-  }
-
   @androidx.compose.Immutable public final class PxSize {
     ctor @kotlin.PublishedApi internal PxSize(internal long value);
     method @androidx.compose.Immutable public androidx.ui.unit.PxSize copy(long value);
@@ -601,7 +518,6 @@
     method @androidx.compose.Stable public operator int compareTo-RjPF0Mw(float p);
     method @androidx.compose.Stable public static operator int compareTo-RjPF0Mw(float $this, float other);
     method public static float constructor-impl(float value);
-    method @androidx.compose.Stable public static inline operator float div-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-bji3ab4(float $this, float other);
     method @androidx.compose.Stable public static inline operator float div-impl(float $this, float other);
@@ -611,7 +527,6 @@
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Stable public static inline operator float minus-RjPF0Mw(float $this, float other);
     method @androidx.compose.Stable public static inline operator float plus-RjPF0Mw(float $this, float other);
-    method @androidx.compose.Stable public static inline operator float times-NgWp0Z8(float $this, float other);
     method @androidx.compose.Stable public static inline operator float times-impl(float $this, float other);
     method @androidx.compose.Stable public static String toString-impl(float $this);
   }
@@ -704,10 +619,10 @@
   }
 
   @androidx.compose.Immutable public final class Velocity {
-    ctor public Velocity(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition component1();
-    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.unit.PxPosition pixelsPerSecond);
-    method public androidx.ui.unit.PxPosition getPixelsPerSecond();
+    ctor public Velocity(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset component1();
+    method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
+    method public androidx.ui.geometry.Offset getPixelsPerSecond();
     method public operator androidx.ui.unit.Velocity unaryMinus();
     field public static final androidx.ui.unit.Velocity.Companion! Companion;
   }
diff --git a/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt
index f5f6022..8069628 100644
--- a/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt
+++ b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt
@@ -19,7 +19,6 @@
 import android.app.Activity
 import android.util.TypedValue
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Rule
@@ -30,8 +29,11 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class DpDeviceTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
 
     private lateinit var activity: Activity
 
diff --git a/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt
index 81e7d6e..9bece1e 100644
--- a/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt
+++ b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt
@@ -19,7 +19,6 @@
 import android.app.Activity
 import android.util.TypedValue
 import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Rule
@@ -30,8 +29,11 @@
 @SmallTest
 @RunWith(JUnit4::class)
 class SpDeviceTest {
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java
+    )
 
     private lateinit var activity: Activity
 
@@ -46,15 +48,15 @@
         val sp10InPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10f, dm)
         with(Density(activity)) {
             assertEquals(sp10InPx, 10.sp.toPx(), 0.01f)
-            assertEquals(10f, Px(sp10InPx).toSp().value, 0.01f)
+            assertEquals(10f, sp10InPx.toSp().value, 0.01f)
         }
     }
 
     @Test
     fun convertSpDp() {
         with(Density(activity)) {
-            val px10InSp = Px(10f).toSp()
-            val px10InDp = Px(10f).toDp()
+            val px10InSp = 10f.toSp()
+            val px10InDp = 10f.toDp()
             assertEquals(px10InDp.value, px10InSp.toDp().value, 0.01f)
             assertEquals(px10InSp.value, px10InDp.toSp().value, 0.01f)
         }
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
index 47c8601..f8828fb 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
@@ -101,18 +101,6 @@
     }
 
     /**
-     * Convert [Px] to [Dp].
-     */
-    @Stable
-    fun Px.toDp(): Dp = (value / density).dp
-
-    /**
-     * Convert [Px] to Sp.
-     */
-    @Stable
-    fun Px.toSp(): TextUnit = (value / (fontScale * density)).sp
-
-    /**
      * Convert [IntPx] to [Dp].
      */
     @Stable
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
index 293b4a8..141f05a 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
@@ -19,6 +19,7 @@
 
 import androidx.compose.Immutable
 import androidx.compose.Stable
+import androidx.ui.geometry.Offset
 import androidx.ui.unit.IntPx.Companion.Infinity
 import androidx.ui.util.lerp
 import androidx.ui.util.packInts
@@ -117,12 +118,6 @@
     @Stable
     override /* TODO: inline */ operator fun compareTo(other: IntPx) = value.compareTo(other.value)
 
-    /**
-     * Compares this [IntPx] to another [Px]
-     */
-    @Stable
-    inline operator fun compareTo(other: Px) = value.compareTo(other.value)
-
     @Stable
     override fun toString() = "$value.ipx"
 
@@ -259,22 +254,6 @@
     return start.keepInfinity(stop, IntPx(lerp(start.value, stop.value, fraction)))
 }
 
-/**
- * Rounds a [Px] size to the nearest Int pixel value.
- */
-@Stable
-inline fun Px.round(): IntPx =
-    if (value.isInfinite()) Infinity else IntPx(value.roundToInt())
-
-/**
- * Rounds up a [Px] to the smallest integer value that is not less than the original value.
- */
-@Stable
-inline fun Px.ceil(): IntPx =
-    if (value.isInfinite()) Infinity else IntPx(kotlin.math.ceil(value).toInt())
-
-inline fun IntPx.toPx(): Px = value.px
-
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 // Structures using IntPx
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
@@ -350,6 +329,20 @@
 }
 
 /**
+ * Subtract a [IntPxPosition] from this [Offset].
+ */
+@Stable
+inline operator fun Offset.minus(other: IntPxPosition) =
+    Offset(x - other.x.value, y - other.y.value)
+
+/**
+ * Add a [IntPxPosition] to this [Offset].
+ */
+@Stable
+inline operator fun Offset.plus(other: IntPxPosition) =
+    Offset(x + other.x.value, y + other.y.value)
+
+/**
  * A two-dimensional position using [IntPx] for units
  */
 @OptIn(ExperimentalUnsignedTypes::class)
@@ -465,20 +458,21 @@
  */
 @Stable
 inline fun PxSize(width: IntPx, height: IntPx): PxSize =
-    PxSize(width = width.toPx(), height = height.toPx())
+    PxSize(width = width.value.toFloat(), height = height.value.toFloat())
 
 /**
- * Create a [PxPosition] from [IntPx] values.
+ * Create a [Offset] from [IntPx] values.
  */
 @Stable
-inline fun PxPosition(x: IntPx, y: IntPx): PxPosition =
-    PxPosition(x = x.toPx().value, y = y.toPx().value)
+inline fun Offset(x: IntPx, y: IntPx): Offset =
+    Offset(x.value.toFloat(), y.value.toFloat())
 
 /**
- * Convert a [IntPxPosition] to a [PxPosition]
+ * Convert a [IntPxPosition] to a [Offset]
  */
 @Stable
-inline fun IntPxPosition.toPxPosition(): PxPosition = PxPosition(this.x, this.y)
+inline fun IntPxPosition.toOffset(): Offset =
+    Offset(x.value.toFloat(), y.value.toFloat())
 
 /**
  * Convert a [IntPxSize] to a [PxSize]
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt
index de88bb7..46fa747 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt
@@ -21,256 +21,16 @@
 import androidx.compose.Stable
 import androidx.ui.geometry.Offset
 import androidx.ui.geometry.Rect
-import androidx.ui.util.lerp
 import androidx.ui.util.packFloats
 import androidx.ui.util.unpackFloat1
 import androidx.ui.util.unpackFloat2
-import kotlin.math.abs
-import kotlin.math.max
 import kotlin.math.min
 import kotlin.math.roundToInt
-import kotlin.math.sqrt
-
-/**
- * Dimension value represented in pixels (px). Component APIs specify their
- * dimensions such as line thickness in DP with Dp objects, while drawing and layout are done
- * in pixel dimensions. When specific pixel dimensions are required, create a Px and convert
- * it to Dp using [Density.toDp]. Px are normally defined using [px], which can be applied to
- * [Int], [Double], and [Float].
- *     val leftMargin = 10.px
- *     val rightMargin = 10f.px
- *     val topMargin = 20.0.px
- *     val bottomMargin = 10.px
- */
-@Suppress("EXPERIMENTAL_FEATURE_WARNING")
-@Immutable
-inline class Px(val value: Float) : Comparable<Px> {
-    /**
-     * Add two [Px]s together.
-     */
-    @Stable
-    inline operator fun plus(other: Px) =
-        Px(value = this.value + other.value)
-
-    /**
-     * Subtract a Px from another one.
-     */
-    @Stable
-    inline operator fun minus(other: Px) =
-        Px(value = this.value - other.value)
-
-    /**
-     * This is the same as multiplying the Px by -1.0.
-     */
-    @Stable
-    inline operator fun unaryMinus() = Px(-value)
-
-    /**
-     * Divide a Px by a scalar.
-     */
-    @Stable
-    inline operator fun div(other: Float): Px =
-        Px(value = value / other)
-
-    @Stable
-    inline operator fun div(other: Int): Px =
-        Px(value = value / other)
-
-    /**
-     * Divide by another Px to get a scalar.
-     */
-    @Stable
-    inline operator fun div(other: Px): Float = value / other.value
-
-    /**
-     * Divide by [PxSquared] to get a [PxInverse].
-     */
-    @Stable
-    inline operator fun div(other: PxSquared): PxInverse =
-        PxInverse(value = value / other.value)
-
-    /**
-     * Multiply a Px by a scalar.
-     */
-    @Stable
-    inline operator fun times(other: Float): Px =
-        Px(value = value * other)
-
-    @Stable
-    inline operator fun times(other: Int): Px =
-        Px(value = value * other)
-
-    /**
-     * Multiply by a Px to get a [PxSquared] result.
-     */
-    @Stable
-    inline operator fun times(other: Px): PxSquared =
-        PxSquared(value = value * other.value)
-
-    /**
-     * Multiply by a Px to get a [PxSquared] result.
-     */
-    @Stable
-    inline operator fun times(other: PxSquared): PxCubed =
-        PxCubed(value = value * other.value)
-
-    /**
-     * Compare [Px] with another [Px].
-     */
-    @Stable
-    override /* TODO: inline */ operator fun compareTo(other: Px) = value.compareTo(other.value)
-
-    /**
-     * Compares this [Px] to another [IntPx]
-     */
-    @Stable
-    inline operator fun compareTo(other: IntPx): Int = value.compareTo(other.value)
-
-    /**
-     * Add an [IntPx] to this [Px].
-     */
-    @Stable
-    inline operator fun plus(other: IntPx) =
-        Px(value = this.value + other.value)
-
-    /**
-     * Subtract an [IntPx] from this [Px].
-     */
-    @Stable
-    inline operator fun minus(other: IntPx) =
-        Px(value = this.value - other.value)
-
-    @Stable
-    override fun toString() = "$value.px"
-
-    companion object {
-        /**
-         * Infinite px dimension.
-         */
-        @Stable
-        val Infinity = Px(value = Float.POSITIVE_INFINITY)
-
-        /**
-         * Zero px dimension
-         */
-        @Stable
-        val Zero = Px(0.0f)
-    }
-}
-
-/**
- * Create a [Px] using an [Int]:
- *     val left = 10
- *     val x = left.px
- *     // -- or --
- *     val y = 10.px
- */
-@Stable
-inline val Int.px: Px get() = Px(value = this.toFloat())
-
-/**
- * Create a [Px] using a [Double]:
- *     val left = 10.0
- *     val x = left.px
- *     // -- or --
- *     val y = 10.0.px
- */
-@Stable
-inline val Double.px: Px get() = Px(value = this.toFloat())
-
-/**
- * Create a [Px] using a [Float]:
- *     val left = 10f
- *     val x = left.px
- *     // -- or --
- *     val y = 10f.px
- */
-@Stable
-inline val Float.px: Px get() = Px(value = this)
-
-@Stable
-inline operator fun Float.div(other: Px) =
-    PxInverse(this / other.value)
-
-@Stable
-inline operator fun Double.div(other: Px) =
-    PxInverse(this.toFloat() / other.value)
-
-@Stable
-inline operator fun Int.div(other: Px) =
-    PxInverse(this / other.value)
-
-@Stable
-inline operator fun Float.times(other: Px) =
-    Px(this * other.value)
-
-@Stable
-inline operator fun Double.times(other: Px) =
-    Px(this.toFloat() * other.value)
-
-@Stable
-inline operator fun Int.times(other: Px) =
-    Px(this * other.value)
-
-@Stable
-inline fun min(a: Px, b: Px): Px = Px(value = min(a.value, b.value))
-
-@Stable
-inline fun max(a: Px, b: Px): Px = Px(value = max(a.value, b.value))
-
-@Stable
-inline fun abs(x: Px): Px = Px(abs(x.value))
-
-/**
- * Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
- *
- * @return this value if it's in the range, or [minimumValue] if this value is less than
- * [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
- */
-@Stable
-inline fun Px.coerceIn(minimumValue: Px, maximumValue: Px): Px =
-    Px(value = value.coerceIn(minimumValue.value, maximumValue.value))
-
-/**
- * Ensures that this value is not less than the specified [minimumValue].
- *
- * @return this value if it's greater than or equal to the [minimumValue] or the
- * [minimumValue] otherwise.
- */
-@Stable
-inline fun Px.coerceAtLeast(minimumValue: Px): Px =
-    Px(value = value.coerceAtLeast(minimumValue.value))
-
-/**
- * Ensures that this value is not greater than the specified [maximumValue].
- *
- * @return this value if it's less than or equal to the [maximumValue] or the
- * [maximumValue] otherwise.
- */
-@Stable
-inline fun Px.coerceAtMost(maximumValue: Px): Px =
-    Px(value = value.coerceAtMost(maximumValue.value))
-
-/**
- * Linearly interpolate between two [Px]s.
- *
- * The [fraction] argument represents position on the timeline, with 0.0 meaning
- * that the interpolation has not started, returning [start] (or something
- * equivalent to [start]), 1.0 meaning that the interpolation has finished,
- * returning [stop] (or something equivalent to [stop]), and values in between
- * meaning that the interpolation is at the relevant point on the timeline
- * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
- * 1.0, so negative values and values greater than 1.0 are valid.
- */
-@Stable
-fun lerp(start: Px, stop: Px, fraction: Float): Px {
-    return Px(lerp(start.value, stop.value, fraction))
-}
 
 /**
  * Holds a unit of squared dimensions, such as `1.value * 2.px`. [PxSquared], [PxCubed],
- * and [PxInverse] are used primarily for [Px] calculations to ensure resulting
- * units are as expected. Many times, [Px] calculations use scalars to determine the final
+ * and [PxInverse] are used primarily for pixel calculations to ensure resulting
+ * units are as expected. Many times, pixel calculations use scalars to determine the final
  * dimension during calculation:
  *     val width = oldWidth * stretchAmount
  * Other times, it is useful to do intermediate calculations with Dimensions directly:
@@ -301,13 +61,6 @@
         PxSquared(value = value / other)
 
     /**
-     * Divide by a [Px] to get a [Px] result.
-     */
-    @Stable
-    inline operator fun div(other: Px): Px =
-        Px(value = value / other.value)
-
-    /**
      * Divide by a PxSquared to get a scalar result.
      */
     @Stable
@@ -328,13 +81,6 @@
         PxSquared(value = value * other)
 
     /**
-     * Multiply by a scalar to get a PxSquared result.
-     */
-    @Stable
-    inline operator fun times(other: Px): PxCubed =
-        PxCubed(value = value * other.value)
-
-    /**
      * Support comparing PxSquared with comparison operators.
      */
     @Stable
@@ -347,8 +93,8 @@
 
 /**
  * Holds a unit of cubed dimensions, such as `1.value * 2.value * 3.px`. [PxSquared],
- * [PxCubed], and [PxInverse] are used primarily for [Px] calculations to
- * ensure resulting units are as expected. Many times, [Px] calculations use scalars to
+ * [PxCubed], and [PxInverse] are used primarily for pixel calculations to
+ * ensure resulting units are as expected. Many times, pixel calculations use scalars to
  * determine the final dimension during calculation:
  *     val width = oldWidth * stretchAmount
  * Other times, it is useful to do intermediate calculations with Dimensions directly:
@@ -379,20 +125,6 @@
         PxCubed(value = value / other)
 
     /**
-     * Divide by a [Px] to get a [PxSquared] result.
-     */
-    @Stable
-    inline operator fun div(other: Px): PxSquared =
-        PxSquared(value = value / other.value)
-
-    /**
-     * Divide by a [PxSquared] to get a [Px] result.
-     */
-    @Stable
-    inline operator fun div(other: PxSquared): Px =
-        Px(value = value / other.value)
-
-    /**
      * Divide by a PxCubed to get a scalar result.
      */
     @Stable
@@ -418,8 +150,8 @@
 
 /**
  * Holds a unit of an inverse dimensions, such as `1.px / (2.value * 3.px)`. [PxSquared],
- * [PxCubed], and [PxInverse] are used primarily for [Px] calculations to
- * ensure resulting units are as expected. Many times, [Px] calculations use scalars to
+ * [PxCubed], and [PxInverse] are used primarily for pixel calculations to
+ * ensure resulting units are as expected. Many times, pixel calculations use scalars to
  * determine the final dimension during calculation:
  *     val width = oldWidth * stretchAmount
  * Other times, it is useful to do intermediate calculations with Dimensions directly:
@@ -457,19 +189,6 @@
         PxInverse(value = value * other)
 
     /**
-     * Multiply by a [Px] to get a scalar result.
-     */
-    @Stable
-    inline operator fun times(other: Px): Float = value * other.value
-
-    /**
-     * Multiply by a [PxSquared] to get a [Px] result.
-     */
-    @Stable
-    inline operator fun times(other: PxSquared): Px =
-        Px(value = value * other.value)
-
-    /**
      * Multiply by a [PxCubed] to get a [PxSquared] result.
      */
     @Stable
@@ -492,20 +211,20 @@
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 /**
- * A two dimensional size using [Px] for units
+ * A two dimensional size using pixels for units
  */
 @Immutable
 data class PxSize @PublishedApi internal constructor(@PublishedApi internal val value: Long) {
 
     /**
-     * The horizontal aspect of the size in [Px].
+     * The horizontal aspect of the size in pixels.
      */
     @Stable
     inline val width: Float
         get() = unpackFloat1(value)
 
     /**
-     * The vertical aspect of the size in [Px].
+     * The vertical aspect of the size in pixels.
      */
     @Stable
     inline val height: Float
@@ -576,12 +295,6 @@
 inline fun PxSize(width: Float, height: Float): PxSize = PxSize(packFloats(width, height))
 
 /**
- * Constructs a [PxSize] from width and height [Px] values.
- */
-@Stable
-inline fun PxSize(width: Px, height: Px): PxSize = PxSize(packFloats(width.value, height.value))
-
-/**
  * Returns a [PxSize] with [size]'s [PxSize.width] and [PxSize.height] multiplied by [this]
  */
 @Stable
@@ -600,12 +313,12 @@
 inline operator fun Double.times(size: PxSize) = size * this
 
 /**
- * Returns the [PxPosition] of the center of the rect from the point of [0, 0]
+ * Returns the [Offset] of the center of the rect from the point of [0, 0]
  * with this [PxSize].
  */
 @Stable
-fun PxSize.center(): PxPosition {
-    return PxPosition(width / 2f, height / 2f)
+fun PxSize.center(): Offset {
+    return Offset(width / 2f, height / 2f)
 }
 
 /**
@@ -615,103 +328,10 @@
 val PxSize.minDimension get() = min(width, height)
 
 /**
- * A two-dimensional position using [Px] for units
- */
-@Immutable
-data class PxPosition @PublishedApi internal constructor(@PublishedApi internal val value: Long) {
-    /**
-     * The horizontal aspect of the position in [Px]
-     */
-    inline val x: Float
-        get() = unpackFloat1(value)
-
-    /**
-     * The vertical aspect of the position in [Px]
-     */
-    inline val y: Float
-        get() = unpackFloat2(value)
-
-    /**
-     * Subtract a [PxPosition] from another one.
-     */
-    @Stable
-    inline operator fun minus(other: PxPosition) =
-        PxPosition(x - other.x, y - other.y)
-
-    /**
-     * Add a [PxPosition] to another one.
-     */
-    @Stable
-    inline operator fun plus(other: PxPosition) =
-        PxPosition(x + other.x, y + other.y)
-
-    /**
-     * Subtract a [IntPxPosition] from this [PxPosition].
-     */
-    @Stable
-    inline operator fun minus(other: IntPxPosition) =
-        PxPosition(x - other.x.value, y - other.y.value)
-
-    /**
-     * Add a [IntPxPosition] to this [PxPosition].
-     */
-    @Stable
-    inline operator fun plus(other: IntPxPosition) =
-        PxPosition(x + other.x.value, y + other.y.value)
-
-    /**
-     * Returns a new PxPosition representing the negation of this point.
-     */
-    @Stable
-    inline operator fun unaryMinus() = PxPosition(-x, -y)
-
-    @Stable
-    override fun toString(): String = "($x, $y)"
-
-    companion object {
-        @Stable
-        val Origin = PxPosition(0.0f, 0.0f)
-    }
-}
-
-/**
- * Constructs a [PxPosition] from [x] and [y] position pixel values.
+ * Round a [Offset] down to the nearest [Int] coordinates.
  */
 @Stable
-inline fun PxPosition(x: Float, y: Float): PxPosition = PxPosition(packFloats(x, y))
-
-/**
- * The magnitude of the offset represented by this [PxPosition].
- */
-@Stable
-fun PxPosition.getDistance(): Px = Px(sqrt(x * x + y * y))
-
-/**
- * Convert a [PxPosition] to a [Offset].
- */
-@Stable
-inline fun PxPosition.toOffset(): Offset = Offset(x, y)
-
-/**
- * Round a [PxPosition] down to the nearest [Int] coordinates.
- */
-@Stable
-inline fun PxPosition.round(): IntPxPosition = IntPxPosition(x.roundToInt().ipx, y.roundToInt().ipx)
-
-/**
- * Linearly interpolate between two [PxPosition]s.
- *
- * The [fraction] argument represents position on the timeline, with 0.0 meaning
- * that the interpolation has not started, returning [start] (or something
- * equivalent to [start]), 1.0 meaning that the interpolation has finished,
- * returning [stop] (or something equivalent to [stop]), and values in between
- * meaning that the interpolation is at the relevant point on the timeline
- * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
- * 1.0, so negative values and values greater than 1.0 are valid.
- */
-@Stable
-fun lerp(start: PxPosition, stop: PxPosition, fraction: Float): PxPosition =
-    PxPosition(lerp(start.x, stop.x, fraction), lerp(start.y, stop.y, fraction))
+inline fun Offset.round(): IntPxPosition = IntPxPosition(x.roundToInt().ipx, y.roundToInt().ipx)
 
 /**
  * A four dimensional bounds using pixels for units
@@ -725,7 +345,7 @@
 )
 
 @Stable
-inline fun PxBounds(topLeft: PxPosition, size: PxSize) =
+inline fun PxBounds(topLeft: Offset, size: PxSize) =
     PxBounds(
         left = topLeft.x,
         top = topLeft.y,
@@ -734,23 +354,23 @@
     )
 
 /**
- * A width of this PxBounds in [Px].
+ * A width of this PxBounds in pixels.
  */
 @Stable
 inline val PxBounds.width: Float get() = right - left
 
 /**
- * A height of this PxBounds in [Px].
+ * A height of this PxBounds in pixels.
  */
 @Stable
 inline val PxBounds.height: Float get() = bottom - top
 
 /**
- * Returns the [PxPosition] of the center of the [PxBounds].
+ * Returns the [Offset] of the center of the [PxBounds].
  */
 @Stable
-inline fun PxBounds.center(): PxPosition {
-    return PxPosition(left + width / 2f, top + height / 2f)
+inline fun PxBounds.center(): Offset {
+    return Offset(left + width / 2f, top + height / 2f)
 }
 
 /**
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt
index d86fb0e..d0451c1 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt
@@ -17,12 +17,13 @@
 package androidx.ui.unit
 
 import androidx.compose.Immutable
+import androidx.ui.geometry.Offset
 
 /** A velocity in two dimensions. */
 @Immutable
 data class Velocity(
     /** The number of pixels per second of velocity in the x and y directions. */
-    val pixelsPerSecond: PxPosition
+    val pixelsPerSecond: Offset
 ) {
     /** Return the negation of a velocity. */
     operator fun unaryMinus() =
@@ -32,7 +33,7 @@
         /**
          * Velocity of 0 pixels per second in both x and y.
          */
-        val Zero = Velocity(PxPosition(0f, 0f))
+        val Zero = Velocity(Offset(0f, 0f))
     }
 }
 
diff --git a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt
index 0a19eea..e7a24ce 100644
--- a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt
+++ b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.unit
 
+import androidx.ui.geometry.Offset
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -215,21 +216,13 @@
     }
 
     @Test
-    fun round() {
-        assertEquals(0, 0.px.round().value)
-        assertEquals(0, 0.25.px.round().value)
-        assertEquals(1, 0.5.px.round().value)
-        assertEquals(99, 99.49.px.round().value)
-    }
-
-    @Test
     fun createSize() {
         assertEquals(PxSize(10f, 20f), PxSize(10.ipx, 20.ipx))
     }
 
     @Test
     fun createPosition() {
-        assertEquals(PxPosition(10f, 20f), PxPosition(10.ipx, 20.ipx))
+        assertEquals(Offset(10f, 20f), Offset(10.ipx, 20.ipx))
     }
 
     @Test
diff --git a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt
index 9b5173d..1c508fa 100644
--- a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt
+++ b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt
@@ -16,176 +16,16 @@
 
 package androidx.ui.unit
 
+import androidx.ui.geometry.Offset
+import androidx.ui.geometry.lerp
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
 @RunWith(JUnit4::class)
 class PxTest {
-    @Test
-    fun constructor() {
-        val dim1 = Px(value = 5f)
-        assertEquals(5f, dim1.value, 0f)
-
-        val dim2 = Px(value = Float.POSITIVE_INFINITY)
-        assertEquals(Float.POSITIVE_INFINITY, dim2.value, 0f)
-
-        val dim3 = Px(value = Float.NaN)
-        assertEquals(Float.NaN, dim3.value, 0f)
-    }
-
-    @Test
-    fun pxIntegerConstruction() {
-        val dim = 10.px
-        assertEquals(10f, dim.value, 0f)
-    }
-
-    @Test
-    fun pxFloatConstruction() {
-        val dim = 10f.px
-        assertEquals(10f, dim.value, 0f)
-    }
-
-    @Test
-    fun pxDoubleConstruction() {
-        val dim = 10.0.px
-        assertEquals(10f, dim.value, 0f)
-    }
-
-    @Test
-    fun subtractOperator() {
-        assertEquals(-1f, (3.px - 4.px).value)
-        assertEquals(1f, (10.px - 9.px).value, 0f)
-    }
-
-    @Test
-    fun addOperator() {
-        assertEquals(2.5f, (1.5.px + 1.ipx).value)
-        assertEquals(10.25f, (6.25.px + 4.ipx).value)
-    }
-
-    @Test
-    fun subtractIntPxOperator() {
-        assertEquals(-.5f, (3.5.px - 4.ipx).value)
-        assertEquals(1.25f, (10.25.px - 9.ipx).value)
-    }
-
-    @Test
-    fun addIntPxOperator() {
-        assertEquals(2f, (1.px + 1.px).value, 0f)
-        assertEquals(10f, (6.px + 4.px).value, 0f)
-    }
-
-    @Test
-    fun multiplyOperator() {
-        assertEquals(0f, (1.px * 0f).value, 0f)
-        assertEquals(10f, (1.px * 10f).value, 0f)
-    }
-
-    @Test
-    fun multiplyOperatorScalar() {
-        assertEquals(10f, 10f * 1.px.value, 0f)
-        assertEquals(10f, 10 * 1.px.value, 0f)
-        assertEquals(10f, (10.0 * 1.px).value, 0f)
-    }
-
-    @Test
-    fun multiplyDimension() {
-        assertEquals(PxSquared(40f), 10.px * 4.px)
-    }
-
-    @Test
-    fun multiplyDimensionSquared() {
-        assertEquals(PxCubed(40f), 10.px * (2.px * 2.px))
-    }
-
-    @Test
-    fun divideOperator() {
-        assertEquals(10f, 100.px / 10f.px, 0f)
-        assertEquals(0f, 0.px / 10f.px, 0f)
-    }
-
-    @Test
-    fun divideOperatorInverse() {
-        assertEquals(PxInverse(10f), 100f / 10.px)
-        assertEquals(PxInverse(10f), 100.0 / 10.px)
-        assertEquals(PxInverse(10f), 100 / 10.px)
-    }
-
-    @Test
-    fun divideToScalar() {
-        assertEquals(1f, 1.px / 1.px, 0f)
-    }
-
-    @Test
-    fun divideToInverse() {
-        assertEquals(PxInverse(10f), 100.px / (5.px * 2.px))
-    }
-
-    @Test
-    fun infinite() {
-        assertEquals(Float.POSITIVE_INFINITY, Px.Infinity.value, 0f)
-    }
-
-    @Suppress("DIVISION_BY_ZERO")
-    @Test
-    fun compare() {
-        assertTrue(0.px < Float.MIN_VALUE.px)
-        assertTrue(1.px < 3.px)
-        assertEquals(0, 1.px.compareTo(1.px))
-        assertTrue(1.px > 0.px)
-        assertTrue(Float.NEGATIVE_INFINITY.px < Px.Infinity)
-        assertTrue(Float.NEGATIVE_INFINITY.px < 0.px)
-        assertTrue(Px.Infinity > Float.MAX_VALUE.px)
-
-        val zeroNaN = 0f / 0f
-        val infNaN = Float.POSITIVE_INFINITY / Float.NEGATIVE_INFINITY
-        assertEquals(0, zeroNaN.px.compareTo(zeroNaN.px))
-        assertEquals(0, infNaN.px.compareTo(infNaN.px))
-    }
-
-    @Test
-    fun addDimension2() {
-        assertEquals(PxSquared(4f), (2.px * 1.px) + (1.px * 2.px))
-    }
-
-    @Test
-    fun subtractDimension2() {
-        assertEquals(PxSquared(0f), (2.px * 3.px) - (3.px * 2.px))
-    }
-
-    @Test
-    fun divideDimension2() {
-        assertEquals(PxSquared(1f), (2.px * 5.px) / 10f)
-    }
-
-    @Test
-    fun divideDimension2Dimension() {
-        assertEquals(1f, ((2.px * 2.px) / 4.px).value, 0f)
-    }
-
-    @Test
-    fun divideDimension2Dimension2() {
-        assertEquals(1f, (2.px * 2.px) / (2.px * 2.px))
-    }
-
-    @Test
-    fun divideDimension2Dimension3() {
-        assertEquals(PxInverse(0.5f), (2.px * 2.px) / (2.px * 2.px * 2.px))
-    }
-
-    @Test
-    fun multiplyDimension2() {
-        assertEquals(PxSquared(4f), (2.px * 1.px) * 2f)
-    }
-
-    @Test
-    fun multiplyDimension2Dimension() {
-        assertEquals(PxCubed(4f), (2.px * 1.px) * 2.px)
-    }
 
     @Test
     fun compareDimension2() {
@@ -196,41 +36,6 @@
     }
 
     @Test
-    fun addDimension3() {
-        assertEquals(PxCubed(4f), (2.px * 1.px * 1.px) + (1.px * 2.px * 1.px))
-    }
-
-    @Test
-    fun subtractDimension3() {
-        assertEquals(PxCubed(0f), (2.px * 3.px * 1.px) - (3.px * 2.px * 1.px))
-    }
-
-    @Test
-    fun divideDimension3() {
-        assertEquals(PxCubed(1f), (2.px * 5.px * 1.px) / 10f)
-    }
-
-    @Test
-    fun divideDimension3Dimension() {
-        assertEquals(PxSquared(1f), (2.px * 2.px * 1.px) / 4.px)
-    }
-
-    @Test
-    fun divideDimension3Dimension2() {
-        assertEquals(1f, ((2.px * 2.px * 1.px) / (2.px * 2.px)).value, 0f)
-    }
-
-    @Test
-    fun divideDimension3Dimension3() {
-        assertEquals(1f, (2.px * 2.px * 1.px) / (2.px * 2.px * 1.px))
-    }
-
-    @Test
-    fun multiplyDimension3() {
-        assertEquals(PxCubed(4f), (2.px * 1.px * 1.px) * 2f)
-    }
-
-    @Test
     fun compareDimension3() {
         assertTrue(PxCubed(0f) < PxCubed(Float.MIN_VALUE))
         assertTrue(PxCubed(1f) < PxCubed(3f))
@@ -239,41 +44,6 @@
     }
 
     @Test
-    fun addDimensionInverse() {
-        assertEquals(PxInverse(1f), 1 / 2.px + 1 / 2.px)
-    }
-
-    @Test
-    fun subtractDimensionInverse() {
-        assertEquals(PxInverse(0f), 1 / 2.px - 1 / 2.px)
-    }
-
-    @Test
-    fun divideDimensionInverse() {
-        assertEquals(PxInverse(1f), (10 / 1.px) / 10f)
-    }
-
-    @Test
-    fun multiplyDimensionInverse() {
-        assertEquals(PxInverse(4f), (1 / 2.px) * 8f)
-    }
-
-    @Test
-    fun multiplyDimensionInverseDimension() {
-        assertEquals(4f, (1 / 2.px) * 8.px)
-    }
-
-    @Test
-    fun multiplyDimensionInverseDimension2() {
-        assertEquals(4f, ((1 / 2.px) * (8.px * 1.px)).value, 0f)
-    }
-
-    @Test
-    fun multiplyDimensionInverseDimension3() {
-        assertEquals(PxSquared(4f), (1 / 2.px) * (8.px * 1.px * 1.px))
-    }
-
-    @Test
     fun compareDimensionInverse() {
         assertTrue(PxInverse(0f) < PxInverse(Float.MIN_VALUE))
         assertTrue(PxInverse(1f) < PxInverse(3f))
@@ -282,95 +52,54 @@
     }
 
     @Test
-    fun minTest() {
-        assertEquals(10f, min(10.px, 20.px).value, 0f)
-        assertEquals(10f, min(20.px, 10.px).value, 0f)
-        assertEquals(10f, min(10.px, 10.px).value, 0f)
-    }
-
-    @Test
-    fun maxTest() {
-        assertEquals(20f, max(10.px, 20.px).value, 0f)
-        assertEquals(20f, max(20.px, 10.px).value, 0f)
-        assertEquals(20f, max(20.px, 20.px).value, 0f)
-    }
-
-    @Test
-    fun coerceIn() {
-        assertEquals(10f, 10.px.coerceIn(0.px, 20.px).value, 0f)
-        assertEquals(10f, 20.px.coerceIn(0.px, 10.px).value, 0f)
-        assertEquals(10f, 0.px.coerceIn(10.px, 20.px).value, 0f)
-        try {
-            10.px.coerceIn(20.px, 10.px)
-            fail("Expected an exception here")
-        } catch (e: IllegalArgumentException) {
-            // success!
-        }
-    }
-
-    @Test
-    fun coerceAtLeast() {
-        assertEquals(10f, 0.px.coerceAtLeast(10.px).value, 0f)
-        assertEquals(10f, 10.px.coerceAtLeast(5.px).value, 0f)
-        assertEquals(10f, 10.px.coerceAtLeast(10.px).value, 0f)
-    }
-
-    @Test
-    fun coerceAtMost() {
-        assertEquals(10f, 100.px.coerceAtMost(10.px).value, 0f)
-        assertEquals(10f, 10.px.coerceAtMost(20.px).value, 0f)
-        assertEquals(10f, 10.px.coerceAtMost(10.px).value, 0f)
-    }
-
-    @Test
     fun sizeCenter() {
-        val size = PxSize(width = 10.px, height = 20.px)
-        assertEquals(PxPosition(5f, 10f), size.center())
+        val size = PxSize(width = 10f, height = 20f)
+        assertEquals(Offset(5f, 10f), size.center())
     }
 
     @Test
     fun positionDistance() {
-        val position = PxPosition(3f, 4f)
-        assertEquals(5.px, position.getDistance())
+        val position = Offset(3f, 4f)
+        assertEquals(5f, position.getDistance())
     }
 
     @Test
     fun lerpPosition() {
-        val a = PxPosition(3f, 10f)
-        val b = PxPosition(5f, 8f)
-        assertEquals(PxPosition(4f, 9f), lerp(a, b, 0.5f))
-        assertEquals(PxPosition(3f, 10f), lerp(a, b, 0f))
-        assertEquals(PxPosition(5f, 8f), lerp(a, b, 1f))
+        val a = Offset(3f, 10f)
+        val b = Offset(5f, 8f)
+        assertEquals(Offset(4f, 9f), lerp(a, b, 0.5f))
+        assertEquals(Offset(3f, 10f), lerp(a, b, 0f))
+        assertEquals(Offset(5f, 8f), lerp(a, b, 1f))
     }
 
     @Test
     fun positionMinus() {
-        val a = PxPosition(3f, 10f)
-        val b = PxPosition(5f, 8f)
-        assertEquals(PxPosition(-2f, 2f), a - b)
-        assertEquals(PxPosition(2f, -2f), b - a)
+        val a = Offset(3f, 10f)
+        val b = Offset(5f, 8f)
+        assertEquals(Offset(-2f, 2f), a - b)
+        assertEquals(Offset(2f, -2f), b - a)
     }
 
     @Test
     fun positionPlus() {
-        val a = PxPosition(3f, 10f)
-        val b = PxPosition(5f, 8f)
-        assertEquals(PxPosition(8f, 18f), a + b)
-        assertEquals(PxPosition(8f, 18f), b + a)
+        val a = Offset(3f, 10f)
+        val b = Offset(5f, 8f)
+        assertEquals(Offset(8f, 18f), a + b)
+        assertEquals(Offset(8f, 18f), b + a)
     }
 
     @Test
     fun pxPositionMinusIntPxPosition() {
-        val a = PxPosition(3f, 10f)
+        val a = Offset(3f, 10f)
         val b = IntPxPosition(5.ipx, 8.ipx)
-        assertEquals(PxPosition(-2f, 2f), a - b)
+        assertEquals(Offset(-2f, 2f), a - b)
     }
 
     @Test
     fun pxPositionPlusIntPxPosition() {
-        val a = PxPosition(3f, 10f)
+        val a = Offset(3f, 10f)
         val b = IntPxPosition(5.ipx, 8.ipx)
-        assertEquals(PxPosition(8f, 18f), a + b)
+        assertEquals(Offset(8f, 18f), a + b)
     }
 
     @Test
diff --git a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt
index 1775a0c..e4c3097 100644
--- a/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt
+++ b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.unit
 
+import androidx.ui.geometry.Offset
 import com.google.common.truth.Truth
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -24,30 +25,30 @@
 @RunWith(JUnit4::class)
 class VelocityTest {
 
-    private val velocity1 = Velocity(pixelsPerSecond = PxPosition(3f, -7f))
-    private val velocity2 = Velocity(pixelsPerSecond = PxPosition(5f, 13f))
+    private val velocity1 = Velocity(pixelsPerSecond = Offset(3f, -7f))
+    private val velocity2 = Velocity(pixelsPerSecond = Offset(5f, 13f))
 
     @Test
     fun operatorUnaryMinus() {
         Truth.assertThat(-velocity1)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(-3f, 7f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(-3f, 7f)))
         Truth.assertThat(-velocity2)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(-5f, -13f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(-5f, -13f)))
     }
 
     @Test
     fun operatorPlus() {
         Truth.assertThat(velocity2 + velocity1)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(8f, 6f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(8f, 6f)))
         Truth.assertThat(velocity1 + velocity2)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(8f, 6f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(8f, 6f)))
     }
 
     @Test
     fun operatorMinus() {
         Truth.assertThat(velocity1 - velocity2)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(-2f, -20f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(-2f, -20f)))
         Truth.assertThat(velocity2 - velocity1)
-            .isEqualTo(Velocity(pixelsPerSecond = PxPosition(2f, 20f)))
+            .isEqualTo(Velocity(pixelsPerSecond = Offset(2f, 20f)))
     }
 }
\ No newline at end of file
diff --git a/ui/ui-util/api/0.1.0-dev14.txt b/ui/ui-util/api/0.1.0-dev14.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/0.1.0-dev14.txt
+++ b/ui/ui-util/api/0.1.0-dev14.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/api/current.txt b/ui/ui-util/api/current.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/current.txt
+++ b/ui/ui-util/api/current.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-util/api/public_plus_experimental_0.1.0-dev14.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-util/api/public_plus_experimental_0.1.0-dev14.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/api/public_plus_experimental_current.txt b/ui/ui-util/api/public_plus_experimental_current.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/public_plus_experimental_current.txt
+++ b/ui/ui-util/api/public_plus_experimental_current.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/api/restricted_0.1.0-dev14.txt b/ui/ui-util/api/restricted_0.1.0-dev14.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-util/api/restricted_0.1.0-dev14.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/api/restricted_current.txt b/ui/ui-util/api/restricted_current.txt
index be129db..11414d6 100644
--- a/ui/ui-util/api/restricted_current.txt
+++ b/ui/ui-util/api/restricted_current.txt
@@ -5,6 +5,10 @@
     method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
   }
 
+  public final class CharHelpersKt {
+    method public static boolean isSurrogatePair(char high, char low);
+  }
+
   public final class InlineClassHelperKt {
     method public static inline long packFloats(float val1, float val2);
     method public static inline long packInts(int val1, int val2);
@@ -14,6 +18,11 @@
     method public static inline int unpackInt2(long value);
   }
 
+  public final class JvmCharHelpersKt {
+    method public static int findFollowingBreak(String, int index);
+    method public static int findPrecedingBreak(String, int index);
+  }
+
   public final class JvmMathHelpersKt {
     method public static String toStringAsFixed(float, int digits);
   }
@@ -33,6 +42,10 @@
     method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
     method public static inline <T> void fastForEachIndexed(java.util.List<? extends T>, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super T,kotlin.Unit> action);
+    method public static inline <T, R> java.util.List<R> fastMap(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R, C extends java.util.Collection<? super R>> C fastMapTo(java.util.List<? extends T>, C destination, kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    method public static inline <T, R extends java.lang.Comparable<? super R>> T? fastMaxBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,? extends R> selector);
+    method public static inline <T> int fastSumBy(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
   }
 
   public final class MathHelpersKt {
@@ -40,6 +53,7 @@
     method public static int lerp(int start, int stop, float fraction);
     method public static long lerp(long start, long stop, float fraction);
     method public static String toHexString(int);
+    method public static float toRadians(float);
     method public static double toRadians(double);
   }
 
diff --git a/ui/ui-util/build.gradle b/ui/ui-util/build.gradle
index 5f8d4e6..a66fe82 100644
--- a/ui/ui-util/build.gradle
+++ b/ui/ui-util/build.gradle
@@ -30,6 +30,7 @@
 
 kotlin {
     android()
+
     sourceSets {
         commonMain.dependencies {
             implementation(KOTLIN_STDLIB_COMMON)
diff --git a/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt
index f31ea68..d57b7fc 100644
--- a/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt
+++ b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt
@@ -29,4 +29,4 @@
     } finally {
         Trace.endSection()
     }
-}
+}
\ No newline at end of file
diff --git a/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt
index b407c4a..8c43efc8 100644
--- a/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt
+++ b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt
@@ -21,4 +21,5 @@
 actual typealias IntRange = androidx.annotation.IntRange
 actual typealias Size = androidx.annotation.Size
 actual typealias GuardedBy = androidx.annotation.GuardedBy
-actual typealias VisibleForTesting = androidx.annotation.VisibleForTesting
\ No newline at end of file
+actual typealias VisibleForTesting = androidx.annotation.VisibleForTesting
+actual typealias CallSuper = androidx.annotation.CallSuper
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/RippleSamples.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/CharHelpers.kt
similarity index 60%
rename from ui/ui-material/samples/src/main/java/androidx/ui/material/samples/RippleSamples.kt
rename to ui/ui-util/src/commonMain/kotlin/androidx/ui/util/CharHelpers.kt
index 81ad8f0..74a7db5 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/RippleSamples.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/CharHelpers.kt
@@ -13,18 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.ui.util
 
-package androidx.ui.material.samples
+fun isSurrogatePair(high: Char, low: Char): Boolean = high.isHighSurrogate() && low.isLowSurrogate()
 
-import androidx.annotation.Sampled
-import androidx.compose.Composable
-import androidx.ui.core.Modifier
-import androidx.ui.foundation.Text
-import androidx.ui.foundation.clickable
-import androidx.ui.material.ripple.ripple
+// Returns -1 if cannot go back.
+expect fun String.findPrecedingBreak(index: Int): Int
 
-@Sampled
-@Composable
-fun RippleSample() {
-    Text(text = "Clickable text", modifier = Modifier.ripple().clickable { /* do something */ })
-}
\ No newline at end of file
+// Returns -1 if cannot go forward.
+expect fun String.findFollowingBreak(index: Int): Int
\ No newline at end of file
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
index fe83593..a88ad51 100644
--- a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
@@ -16,6 +16,8 @@
 
 package androidx.ui.util
 
+import kotlin.collections.ArrayList
+
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEach].
@@ -52,4 +54,61 @@
 inline fun <T> List<T>.fastFirstOrNull(predicate: (T) -> Boolean): T? {
     fastForEach { if (predicate(it)) return it }
     return null
-}
\ No newline at end of file
+}
+
+/**
+ * Returns the sum of all values produced by [selector] function applied to each element in the
+ * list.
+ */
+inline fun <T> List<T>.fastSumBy(selector: (T) -> Int): Int {
+    var sum = 0
+    fastForEach { element ->
+        sum += selector(element)
+    }
+    return sum
+}
+
+/**
+ * Returns a list containing the results of applying the given [transform] function
+ * to each element in the original collection.
+ */
+inline fun <T, R> List<T>.fastMap(transform: (T) -> R): List<R> {
+    val target = ArrayList<R>()
+    fastForEach {
+        target += transform(it)
+    }
+    return target
+}
+
+/**
+ * Returns the first element yielding the largest value of the given function or `null` if there
+ * are no elements.
+ */
+inline fun <T, R : Comparable<R>> List<T>.fastMaxBy(selector: (T) -> R): T? {
+    if (isEmpty()) return null
+    var maxElem = get(0)
+    var maxValue = selector(maxElem)
+    for (i in 1..lastIndex) {
+        val e = get(i)
+        val v = selector(e)
+        if (maxValue < v) {
+            maxElem = e
+            maxValue = v
+        }
+    }
+    return maxElem
+}
+
+/**
+ * Applies the given [transform] function to each element of the original collection
+ * and appends the results to the given [destination].
+ */
+inline fun <T, R, C : MutableCollection<in R>> List<T>.fastMapTo(
+    destination: C,
+    transform: (T) -> R
+): C {
+    fastForEach { item ->
+        destination.add(transform(item))
+    }
+    return destination
+}
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
index 615a141..4bd3af4 100644
--- a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
@@ -45,4 +45,5 @@
 @OptIn(kotlin.ExperimentalUnsignedTypes::class)
 fun Int.toHexString() = "0x${toUInt().toString(16).padStart(8, '0')}"
 
-fun Double.toRadians(): Double = this / 180 * PI
\ No newline at end of file
+fun Float.toRadians(): Float = this / 180f * PI.toFloat()
+fun Double.toRadians(): Double = this / 180 * PI
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt
index 3bee49a..d23fef5 100644
--- a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt
@@ -53,3 +53,7 @@
 expect annotation class VisibleForTesting(
     val otherwise: Int = 2
 )
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class CallSuper()
\ No newline at end of file
diff --git a/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmCharHelpers.kt b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmCharHelpers.kt
new file mode 100644
index 0000000..5455a05
--- /dev/null
+++ b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmCharHelpers.kt
@@ -0,0 +1,32 @@
+
+/*
+ * 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.util
+
+import java.text.BreakIterator
+
+actual fun String.findPrecedingBreak(index: Int): Int {
+    val it = BreakIterator.getCharacterInstance()
+    it.setText(this)
+    return it.preceding(index)
+}
+
+actual fun String.findFollowingBreak(index: Int): Int {
+    val it = BreakIterator.getCharacterInstance()
+    it.setText(this)
+    return it.following(index)
+}
\ No newline at end of file
diff --git a/ui/ui-vector/build.gradle b/ui/ui-vector/build.gradle
index 2fc9bdf..864c355 100644
--- a/ui/ui-vector/build.gradle
+++ b/ui/ui-vector/build.gradle
@@ -25,16 +25,26 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXUiPlugin")
-    id("org.jetbrains.kotlin.android")
+    id("kotlin-multiplatform")
 }
 
 dependencies {
     kotlinPlugin project(path: ":compose:compose-compiler")
+}
 
-    api project(':ui:ui-graphics')
-    api project(":compose:compose-runtime")
-    implementation project(":ui:ui-util")
-    implementation (KOTLIN_STDLIB)
+kotlin {
+    android()
+    sourceSets {
+        androidMain {
+        }
+
+        commonMain.dependencies {
+            api project(':ui:ui-graphics')
+            api project(":compose:compose-runtime")
+            implementation project(":ui:ui-util")
+            implementation (KOTLIN_STDLIB_COMMON)
+        }
+    }
 }
 
 androidx {
diff --git a/ui/ui-vector/src/main/AndroidManifest.xml b/ui/ui-vector/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-vector/src/main/AndroidManifest.xml
rename to ui/ui-vector/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-vector/src/main/java/androidx/ui/graphics/vector/Vector.kt b/ui/ui-vector/src/commonMain/kotlin/androidx/ui/graphics/vector/Vector.kt
similarity index 95%
rename from ui/ui-vector/src/main/java/androidx/ui/graphics/vector/Vector.kt
rename to ui/ui-vector/src/commonMain/kotlin/androidx/ui/graphics/vector/Vector.kt
index 4dd9faf..98b35131 100644
--- a/ui/ui-vector/src/main/java/androidx/ui/graphics/vector/Vector.kt
+++ b/ui/ui-vector/src/commonMain/kotlin/androidx/ui/graphics/vector/Vector.kt
@@ -16,7 +16,6 @@
 
 package androidx.ui.graphics.vector
 
-import android.graphics.Matrix
 import androidx.ui.geometry.Offset
 import androidx.ui.graphics.BlendMode
 import androidx.ui.graphics.Brush
@@ -29,8 +28,10 @@
 import androidx.ui.graphics.Path
 import androidx.ui.graphics.StrokeCap
 import androidx.ui.graphics.StrokeJoin
+import androidx.ui.graphics.vectormath.Matrix4
 import androidx.ui.graphics.withSave
 import androidx.ui.util.fastForEach
+import androidx.ui.util.toRadians
 import kotlin.math.ceil
 
 const val DefaultGroupName = ""
@@ -135,7 +136,7 @@
             root.draw(Canvas(targetImage))
             isDirty = false
         }
-        canvas.drawImage(targetImage, Offset.zero, obtainVectorPaint(alpha, colorFilter))
+        canvas.drawImage(targetImage, Offset.Zero, obtainVectorPaint(alpha, colorFilter))
     }
 
     override fun draw(canvas: Canvas) {
@@ -350,7 +351,7 @@
 
 data class GroupComponent(val name: String = DefaultGroupName) : VNode() {
 
-    private var groupMatrix: Matrix? = null
+    private var groupMatrix: Matrix4? = null
 
     private val children = mutableListOf<VNode>()
 
@@ -467,22 +468,22 @@
     private var isMatrixDirty = true
 
     private fun updateMatrix() {
-        val matrix: Matrix
+        val matrix: Matrix4
         val target = groupMatrix
         if (target == null) {
-            matrix = Matrix()
+            matrix = Matrix4()
             groupMatrix = matrix
         } else {
             matrix = target
         }
-        with(matrix) {
-            reset()
-            postTranslate(-pivotX, -pivotY)
-            postScale(scaleX, scaleY)
-            postRotate(rotation, 0f, 0f)
-            postTranslate(translationX + pivotX,
-                translationY + pivotY)
-        }
+        matrix.assignColumns(Matrix4.identity())
+        // M = T(translationX + pivotX, translationY + pivotY) *
+        //     R(rotation) * S(scaleX, scaleY) *
+        //     T(-pivotX, -pivotY)
+        matrix.translate(translationX + pivotX, translationY + pivotY)
+        matrix.rotateZ(radians = rotation.toRadians())
+        matrix.scale(scaleX, scaleY, 1f)
+        matrix.translate(-pivotX, -pivotY)
     }
 
     fun insertAt(index: Int, instance: VNode) {
@@ -542,7 +543,7 @@
             val matrix = groupMatrix
             if (matrix != null) {
                 // TODO (njawad) add concat support to matrix
-                canvas.nativeCanvas.concat(matrix)
+                canvas.concat(matrix)
             }
 
             children.fastForEach { node ->
diff --git a/ui/ui-vector/src/main/java/androidx/ui/graphics/vector/VectorComposeNonIR.kt b/ui/ui-vector/src/commonMain/kotlin/androidx/ui/graphics/vector/VectorComposeNonIR.kt
similarity index 100%
rename from ui/ui-vector/src/main/java/androidx/ui/graphics/vector/VectorComposeNonIR.kt
rename to ui/ui-vector/src/commonMain/kotlin/androidx/ui/graphics/vector/VectorComposeNonIR.kt
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
index 4b705e9..665b5b6 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
 import androidx.test.espresso.matcher.ViewMatchers.withId
 import androidx.test.espresso.matcher.ViewMatchers.withText
-import androidx.test.rule.ActivityTestRule
 import androidx.viewpager2.integration.testapp.R
 import androidx.viewpager2.integration.testapp.test.util.ViewPagerIdleWatcher
 import androidx.viewpager2.integration.testapp.test.util.onCurrentPage
@@ -56,9 +55,10 @@
  * @see TabLayoutTest
  */
 abstract class BaseTest<T : FragmentActivity>(clazz: Class<T>) {
+    @Suppress("DEPRECATION")
     @Rule
     @JvmField
-    var activityTestRule = ActivityTestRule(clazz)
+    var activityTestRule = androidx.test.rule.ActivityTestRule(clazz)
 
     @get:LayoutRes
     abstract val layoutId: Int
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
index 688625ca..63486e4 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
@@ -43,7 +43,6 @@
 import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
 import androidx.test.espresso.matcher.ViewMatchers.withId
 import androidx.test.espresso.matcher.ViewMatchers.withText
-import androidx.test.rule.ActivityTestRule
 import androidx.testutils.LocaleTestUtils
 import androidx.testutils.recreate
 import androidx.testutils.waitForExecution
@@ -87,8 +86,13 @@
 
     lateinit var localeUtil: LocaleTestUtils
 
+    @Suppress("DEPRECATION")
     @get:Rule
-    val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java, false, false)
+    val activityTestRule = androidx.test.rule.ActivityTestRule<TestActivity>(
+        TestActivity::class.java,
+        false,
+        false
+    )
 
     @Before
     open fun setUp() {
@@ -124,7 +128,10 @@
         return Context(activityTestRule)
     }
 
-    data class Context(val activityTestRule: ActivityTestRule<TestActivity>) {
+    data class Context(
+        @Suppress("DEPRECATION")
+        val activityTestRule: androidx.test.rule.ActivityTestRule<TestActivity>
+    ) {
         fun recreateActivity(
             adapterProvider: AdapterProvider,
             onCreateCallback: ((ViewPager2) -> Unit) = { }
diff --git a/wear/wear-input-testing/api/1.0.0-alpha01.txt b/wear/wear-input-testing/api/1.0.0-alpha01.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/1.0.0-alpha01.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/api/current.txt b/wear/wear-input-testing/api/current.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/api/public_plus_experimental_1.0.0-alpha01.txt b/wear/wear-input-testing/api/public_plus_experimental_1.0.0-alpha01.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/api/public_plus_experimental_current.txt b/wear/wear-input-testing/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/public_plus_experimental_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/api/res-1.0.0-alpha01.txt b/wear/wear-input-testing/api/res-1.0.0-alpha01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/wear-input-testing/api/res-1.0.0-alpha01.txt
diff --git a/wear/wear-input-testing/api/res-current.txt b/wear/wear-input-testing/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/wear-input-testing/api/res-current.txt
diff --git a/wear/wear-input-testing/api/restricted_1.0.0-alpha01.txt b/wear/wear-input-testing/api/restricted_1.0.0-alpha01.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/restricted_1.0.0-alpha01.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/api/restricted_current.txt b/wear/wear-input-testing/api/restricted_current.txt
new file mode 100644
index 0000000..847f64c
--- /dev/null
+++ b/wear/wear-input-testing/api/restricted_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.wear.input.testing {
+
+  public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+    ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+    method public android.graphics.PointF getLocation();
+    method public android.graphics.PointF? getRotatedLocation();
+  }
+
+}
+
diff --git a/wear/wear-input-testing/build.gradle b/wear/wear-input-testing/build.gradle
new file mode 100644
index 0000000..9e70953
--- /dev/null
+++ b/wear/wear-input-testing/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * 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
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+}
+
+dependencies {
+    api(project(":wear:wear-input"))
+    compileOnly fileTree(dir: '../wear_stubs', include: ['com.google.android.wearable-stubs.jar'])
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+    }
+}
+
+androidx {
+    name = "Android Wear Support Input Testing Helpers"
+    publish = Publish.SNAPSHOT_AND_RELEASE
+    mavenGroup = LibraryGroups.WEAR
+    mavenVersion = LibraryVersions.WEAR_INPUT
+    inceptionYear = "2020"
+    description = "Android Wear Support Input  Testing Helpers"
+}
diff --git a/wear/wear-input-testing/src/main/AndroidManifest.xml b/wear/wear-input-testing/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..70ec2c9
--- /dev/null
+++ b/wear/wear-input-testing/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.wear"/>
diff --git a/wear/wear-input-testing/src/main/java/androidx/wear/input/testing/TestWearableButtonsProvider.java b/wear/wear-input-testing/src/main/java/androidx/wear/input/testing/TestWearableButtonsProvider.java
new file mode 100644
index 0000000..b2ddfc5
--- /dev/null
+++ b/wear/wear-input-testing/src/main/java/androidx/wear/input/testing/TestWearableButtonsProvider.java
@@ -0,0 +1,149 @@
+/*
+ * 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.wear.input.testing;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.wear.input.WearableButtonsProvider;
+
+import com.google.android.wearable.input.WearableInputDevice;
+
+import java.util.Map;
+
+/**
+ * A {@link WearableButtonsProvider} suitable for use in tests.
+ *
+ * <p>This allows for explicitly specifying which buttons are available for testing, and their
+ * coordinates. It is intended to be used by passing in a map, mapping between the button keycode
+ * (typically in the set {@link android.view.KeyEvent#KEYCODE_STEM_PRIMARY}, {@link
+ * android.view.KeyEvent#KEYCODE_STEM_1}, {@link android.view.KeyEvent#KEYCODE_STEM_2}, or {@link
+ * android.view.KeyEvent#KEYCODE_STEM_3}) and the location of the button. Take the following
+ * example:
+ *
+ * <pre>
+ *     Map<Integer, TestWearableButtonLocation> buttons = new HashMap<>();
+ *     buttons.put(KEYCODE_STEM_1, new TestWearableButtonLocation(100, 100);
+ *
+ *     TestWearableButtonsProvider provider = new TestWearableButtonsProvider(buttons);
+ *
+ *     WearableButtons.setWearableButtonsProvider(provider);
+ * </pre>
+ */
+public class TestWearableButtonsProvider implements WearableButtonsProvider {
+
+    /**
+     * Class describing the location of a button on a wearable device. This has two forms; it can
+     * either store the absolute location of the button, or store both the absolute location of the
+     * button, and the absolute location when the screen is rotated through 180 degrees.
+     */
+    public static class TestWearableButtonLocation {
+        private final PointF mLocation;
+        private final PointF mRotatedLocation;
+
+        /**
+         * Build a button location, with just the default button location.
+         *
+         * @param x X coordinate of the button.
+         * @param y Y coordinate of the button.
+         */
+        public TestWearableButtonLocation(float x, float y) {
+            mLocation = new PointF(x, y);
+            mRotatedLocation = null;
+        }
+
+        /**
+         * Build a button location, with both the default button location, and the location when the
+         * device is rotated through 180 degrees.
+         *
+         * @param x X coordinate of the button.
+         * @param y Y coordinate of the button.
+         * @param rotatedX X coordinate of the button when the device is rotated.
+         * @param rotatedY Y coordinate of the button when the device is rotated.
+         */
+        public TestWearableButtonLocation(float x, float y, float rotatedX, float rotatedY) {
+            mLocation = new PointF(x, y);
+            mRotatedLocation = new PointF(rotatedX, rotatedY);
+        }
+
+        /**
+         * Get the location of this button.
+         *
+         * @return A point specifying the location of this button.
+         */
+        @NonNull
+        public PointF getLocation() {
+            return mLocation;
+        }
+
+        /**
+         * Get the location of this button when the device is rotated.
+         *
+         * @return A point specifying the location of this button when the device is rotated.
+         */
+        @Nullable
+        public PointF getRotatedLocation() {
+            return mRotatedLocation;
+        }
+    }
+
+    private final Map<Integer, TestWearableButtonLocation> mButtons;
+
+    /**
+     * Build a button provider, which will respond with the provided set of buttons.
+     *
+     * @param buttons The buttons returned by this provider.
+     */
+    public TestWearableButtonsProvider(@NonNull Map<Integer, TestWearableButtonLocation> buttons) {
+        mButtons = buttons;
+    }
+
+    @NonNull
+    @Override
+    public Bundle getButtonInfo(@NonNull Context context, int keycode) {
+        Bundle bundle = new Bundle();
+
+        TestWearableButtonLocation location = mButtons.get(keycode);
+        if (location != null) {
+            bundle.putFloat(WearableInputDevice.X_KEY, location.getLocation().x);
+            bundle.putFloat(WearableInputDevice.Y_KEY, location.getLocation().y);
+
+            if (location.getRotatedLocation() != null) {
+                bundle.putFloat(WearableInputDevice.X_KEY_ROTATED, location.getRotatedLocation().x);
+                bundle.putFloat(WearableInputDevice.Y_KEY_ROTATED, location.getRotatedLocation().y);
+            }
+        }
+
+        return bundle;
+    }
+
+    @Nullable
+    @Override
+    public int[] getAvailableButtonKeyCodes(@NonNull Context context) {
+        int[] keys = new int[mButtons.size()];
+
+        int i = 0;
+        for (Integer keycode : mButtons.keySet()) {
+            keys[i++] = keycode;
+        }
+
+        return keys;
+    }
+}
diff --git a/wear/wear-input/api/1.0.0-alpha01.txt b/wear/wear-input/api/1.0.0-alpha01.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/1.0.0-alpha01.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/api/current.txt b/wear/wear-input/api/current.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/current.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/api/public_plus_experimental_1.0.0-alpha01.txt b/wear/wear-input/api/public_plus_experimental_1.0.0-alpha01.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/api/public_plus_experimental_current.txt b/wear/wear-input/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/public_plus_experimental_current.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/api/res-1.0.0-alpha01.txt b/wear/wear-input/api/res-1.0.0-alpha01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/wear-input/api/res-1.0.0-alpha01.txt
diff --git a/wear/wear-input/api/res-current.txt b/wear/wear-input/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/wear-input/api/res-current.txt
diff --git a/wear/wear-input/api/restricted_1.0.0-alpha01.txt b/wear/wear-input/api/restricted_1.0.0-alpha01.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/restricted_1.0.0-alpha01.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/api/restricted_current.txt b/wear/wear-input/api/restricted_current.txt
new file mode 100644
index 0000000..9998442
--- /dev/null
+++ b/wear/wear-input/api/restricted_current.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.wear.input {
+
+  public class DeviceWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+    ctor public DeviceWearableButtonsProvider();
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+  public final class WearableButtons {
+    method public static int getButtonCount(android.content.Context);
+    method public static android.graphics.drawable.Drawable? getButtonIcon(android.content.Context, int);
+    method public static androidx.wear.input.WearableButtons.ButtonInfo? getButtonInfo(android.content.Context, int);
+    method public static CharSequence getButtonLabel(android.content.Context, int);
+  }
+
+  public static final class WearableButtons.ButtonInfo {
+    method public int getKeycode();
+    method public int getLocationZone();
+    method public float getX();
+    method public float getY();
+  }
+
+  public interface WearableButtonsProvider {
+    method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+    method public android.os.Bundle getButtonInfo(android.content.Context, int);
+  }
+
+}
+
diff --git a/wear/wear-input/build.gradle b/wear/wear-input/build.gradle
new file mode 100644
index 0000000..5ab8fb0
--- /dev/null
+++ b/wear/wear-input/build.gradle
@@ -0,0 +1,57 @@
+/*
+ * 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 Laicense.
+ * 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 static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+}
+
+dependencies {
+    api("androidx.annotation:annotation:1.1.0")
+
+    testImplementation(ANDROIDX_TEST_EXT_JUNIT)
+    testImplementation(ANDROIDX_TEST_CORE)
+    testImplementation(ANDROIDX_TEST_RUNNER)
+    testImplementation(ANDROIDX_TEST_RULES)
+    testImplementation(ROBOLECTRIC)
+    testImplementation(MOCKITO_CORE)
+    testImplementation(project(":wear:wear-input-testing"))
+
+    compileOnly fileTree(dir: '../wear_stubs', include: ['com.google.android.wearable-stubs.jar'])
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+    }
+
+    // Use Robolectric 4.+
+    testOptions.unitTests.includeAndroidResources = true
+}
+
+androidx {
+    name = "Android Wear Support Input"
+    publish = Publish.SNAPSHOT_AND_RELEASE
+    mavenGroup = LibraryGroups.WEAR
+    mavenVersion = LibraryVersions.WEAR_INPUT
+    inceptionYear = "2020"
+    description = "Android Wear Support Input"
+}
diff --git a/wear/wear-input/src/main/AndroidManifest.xml b/wear/wear-input/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..19e4723a
--- /dev/null
+++ b/wear/wear-input/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.wear.input"/>
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/DeviceWearableButtonsProvider.java b/wear/wear-input/src/main/java/androidx/wear/input/DeviceWearableButtonsProvider.java
new file mode 100644
index 0000000..a8130fb
--- /dev/null
+++ b/wear/wear-input/src/main/java/androidx/wear/input/DeviceWearableButtonsProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.wear.input;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.android.wearable.input.WearableInputDevice;
+
+/**
+ * Default implementation of {@link WearableButtonsProvider}, that reads the button locations from
+ * the platform.
+ */
+public class DeviceWearableButtonsProvider implements WearableButtonsProvider {
+
+    @NonNull
+    @Override
+    public Bundle getButtonInfo(@NonNull Context context, int keycode) {
+        if (!isSharedLibAvailable()) {
+            return null;
+        }
+
+        return WearableInputDevice.getButtonInfo(context, keycode);
+    }
+
+    @Nullable
+    @Override
+    public int[] getAvailableButtonKeyCodes(@NonNull Context context) {
+        if (!isSharedLibAvailable()) {
+            return null;
+        }
+
+        return WearableInputDevice.getAvailableButtonKeyCodes(context);
+    }
+
+    private boolean isSharedLibAvailable() {
+        return SharedLibraryVersion.version() >= 1;
+    }
+}
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/SharedLibraryVersion.java b/wear/wear-input/src/main/java/androidx/wear/input/SharedLibraryVersion.java
new file mode 100644
index 0000000..2a6b0c9
--- /dev/null
+++ b/wear/wear-input/src/main/java/androidx/wear/input/SharedLibraryVersion.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.wear.input;
+
+import android.os.Build;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.google.android.wearable.WearableSharedLib;
+
+/**
+ * Internal class which can be used to determine the version of the wearable shared library that is
+ * available on the current device.
+ */
+final class SharedLibraryVersion {
+
+    private SharedLibraryVersion() {}
+
+    /**
+     * Returns the version of the wearable shared library available on the current device.
+     *
+     * <p>
+     *
+     * <p>Version 1 was introduced on 2016-09-26, so any previous shared library will return 0. In
+     * those cases, it may be necessary to check {@code Build.VERSION.SDK_INT}.
+     *
+     * @throws IllegalStateException if the Wearable Shared Library is not present, which means that
+     *     the {@code <uses-library>} tag is missing.
+     */
+    public static int version() {
+        verifySharedLibraryPresent();
+        return VersionHolder.VERSION;
+    }
+
+    /**
+     * Throws {@link IllegalStateException} if the Wearable Shared Library is not present and API
+     * level is at least LMP MR1.
+     *
+     * <p>
+     *
+     * <p>This validates that the developer hasn't forgotten to include a {@code <uses-library>} tag
+     * in their manifest. The method should be used in combination with API level checks for
+     * features added before {@link #version() version} 1.
+     */
+    public static void verifySharedLibraryPresent() {
+        if (!PresenceHolder.PRESENT) {
+            throw new IllegalStateException(
+                    "Could not find wearable shared library classes. Please add <uses-library"
+                        + " android:name=\"com.google.android.wearable\""
+                        + " android:required=\"false\" /> to the application manifest");
+        }
+    }
+
+    // Lazy initialization holder class (see Effective Java item 71)
+    @VisibleForTesting
+    static final class VersionHolder {
+        static final int VERSION = getSharedLibVersion(Build.VERSION.SDK_INT);
+
+        @VisibleForTesting
+        static int getSharedLibVersion(int sdkInt) {
+            if (sdkInt < Build.VERSION_CODES.N_MR1) {
+                // WearableSharedLib was introduced in N MR1 (Wear FDP 4)
+                return 0;
+            }
+            return WearableSharedLib.version();
+        }
+
+        private VersionHolder() {}
+    }
+
+    // Lazy initialization holder class (see Effective Java item 71)
+    @VisibleForTesting
+    static final class PresenceHolder {
+        static final boolean PRESENT = isSharedLibPresent(Build.VERSION.SDK_INT);
+
+        @VisibleForTesting
+        static boolean isSharedLibPresent(int sdkInt) {
+            try {
+                // A class which has been available on the shared library from the first version.
+                Class.forName("com.google.android.wearable.compat.WearableActivityController");
+            } catch (ClassNotFoundException e) {
+                return false;
+            }
+            return true;
+        }
+
+        private PresenceHolder() {}
+    }
+}
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/WearableButtons.java b/wear/wear-input/src/main/java/androidx/wear/input/WearableButtons.java
new file mode 100644
index 0000000..a2ec7da
--- /dev/null
+++ b/wear/wear-input/src/main/java/androidx/wear/input/WearableButtons.java
@@ -0,0 +1,722 @@
+/*
+ * 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.wear.input;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RotateDrawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
+
+import com.google.android.wearable.input.WearableInputDevice;
+
+/** Class containing helpers for managing wearable buttons. */
+@TargetApi(Build.VERSION_CODES.M)
+public final class WearableButtons {
+
+    private static WearableButtonsProvider sButtonsProvider = new DeviceWearableButtonsProvider();
+
+    /** Represents that the count of available device buttons. */
+    private static volatile int sButtonCount = -1;
+
+    private WearableButtons() {
+        throw new RuntimeException("WearableButtons should not be instantiated");
+    }
+
+    /**
+     * Testing call to allow the underlying {@link WearableButtonsProvider} to be substituted in
+     * test code.
+     *
+     * @param provider The new {@link WearableButtonsProvider} to use.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public static void setWearableButtonsProvider(@NonNull WearableButtonsProvider provider) {
+        sButtonsProvider = provider;
+    }
+
+    /** Represents that the location zone is unknown. */
+    @VisibleForTesting static final int LOC_UNKNOWN = -1;
+
+    /** Represents the east position on a round device. */
+    @VisibleForTesting static final int LOC_EAST = 0;
+
+    /** Represents the east-northeast position on a round device. */
+    @VisibleForTesting static final int LOC_ENE = 1;
+
+    /** Represents the northeast position on a round device. */
+    @VisibleForTesting static final int LOC_NE = 2;
+
+    /** Represents the north-northeast position on a round device. */
+    @VisibleForTesting static final int LOC_NNE = 3;
+
+    /** Represents the north position on a round device. */
+    @VisibleForTesting static final int LOC_NORTH = 4;
+
+    /** Represents the north-northwest position on a round device. */
+    @VisibleForTesting static final int LOC_NNW = 5;
+
+    /** Represents the northwest position on a round device. */
+    @VisibleForTesting static final int LOC_NW = 6;
+
+    /** Represents the west-northwest position on a round device. */
+    @VisibleForTesting static final int LOC_WNW = 7;
+
+    /** Represents the west position on a round device. */
+    @VisibleForTesting static final int LOC_WEST = 8;
+
+    /** Represents the west-southwest position on a round device. */
+    @VisibleForTesting static final int LOC_WSW = 9;
+
+    /** Represents the southwest position on a round device. */
+    @VisibleForTesting static final int LOC_SW = 10;
+
+    /** Represents the south-southwest position on a round device. */
+    @VisibleForTesting static final int LOC_SSW = 11;
+
+    /** Represents the south position on a round device. */
+    @VisibleForTesting static final int LOC_SOUTH = 12;
+
+    /** Represents the south-southeast position on a round device. */
+    @VisibleForTesting static final int LOC_SSE = 13;
+
+    /** Represents the southeast position on a round device. */
+    @VisibleForTesting static final int LOC_SE = 14;
+
+    /** Represents the east-southeast position on a round device. */
+    @VisibleForTesting static final int LOC_ESE = 15;
+
+    private static final int LOC_ROUND_COUNT = 16;
+
+    /** Represents the right third of the top side on a square device. */
+    @VisibleForTesting static final int LOC_TOP_RIGHT = 100;
+
+    /** Represents the center third of the top side on a square device. */
+    @VisibleForTesting static final int LOC_TOP_CENTER = 101;
+
+    /** Represents the left third of the top side on a square device. */
+    @VisibleForTesting static final int LOC_TOP_LEFT = 102;
+
+    /** Represents the top third of the left side on a square device. */
+    @VisibleForTesting static final int LOC_LEFT_TOP = 103;
+
+    /** Represents the center third of the left side on a square device. */
+    @VisibleForTesting static final int LOC_LEFT_CENTER = 104;
+
+    /** Represents the bottom third of the left side on a square device. */
+    @VisibleForTesting static final int LOC_LEFT_BOTTOM = 105;
+
+    /** Represents the left third of the bottom side on a square device. */
+    @VisibleForTesting static final int LOC_BOTTOM_LEFT = 106;
+
+    /** Represents the center third of the bottom side on a square device. */
+    @VisibleForTesting static final int LOC_BOTTOM_CENTER = 107;
+
+    /** Represents the right third of the bottom side on a square device. */
+    @VisibleForTesting static final int LOC_BOTTOM_RIGHT = 108;
+
+    /** Represents the bottom third of the right side on a square device. */
+    @VisibleForTesting static final int LOC_RIGHT_BOTTOM = 109;
+
+    /** Represents the center third of the right side on a square device. */
+    @VisibleForTesting static final int LOC_RIGHT_CENTER = 110;
+
+    /** Represents the top third of the right side on a square device. */
+    @VisibleForTesting static final int LOC_RIGHT_TOP = 111;
+
+    /**
+     * Key used with the bundle returned by {@link #getButtonInfo}} to retrieve the x coordinate of
+     * a button when the screen is rotated 180 degrees. (temporary copy from WearableInputDevice)
+     */
+    private static final String X_KEY_ROTATED = "x_key_rotated";
+
+    /**
+     * Key used with the bundle returned by {@link #getButtonInfo}} to retrieve the y coordinate of
+     * a button when the screen is rotated 180 degrees. (temporary copy from WearableInputDevice)
+     */
+    private static final String Y_KEY_ROTATED = "y_key_rotated";
+
+    /**
+     * Returns a {@link ButtonInfo} containing the metadata for a specific button.
+     *
+     * <p>The location will be populated in the following manner:
+     *
+     * <ul>
+     *   <li>The provided point will be on the screen, or more typically, on the edge of the screen.
+     *   <li>The point won't be off the edge of the screen.
+     *   <li>The location returned is a screen coordinate. The unit of measurement is in pixels. The
+     *       coordinates do not take rotation into account and assume that the device is in the
+     *       standard upright position.
+     * </ul>
+     *
+     * <p>Common keycodes to use are {@link android.view.KeyEvent#KEYCODE_STEM_PRIMARY}, {@link
+     * android.view.KeyEvent#KEYCODE_STEM_1}, {@link android.view.KeyEvent#KEYCODE_STEM_2}, and
+     * {@link android.view.KeyEvent#KEYCODE_STEM_3}.
+     *
+     * @param context The context of the current activity
+     * @param keycode The keycode associated with the hardware button of interest
+     * @return A {@link ButtonInfo} containing the metadata for the given keycode or null if the
+     *     information is not available
+     */
+    @Nullable
+    public static ButtonInfo getButtonInfo(@NonNull Context context, int keycode) {
+        Bundle bundle = sButtonsProvider.getButtonInfo(context, keycode);
+
+        if (bundle == null) {
+            return null;
+        }
+
+        // If the information is not available, return null
+        if (!bundle.containsKey(WearableInputDevice.X_KEY)
+                || !bundle.containsKey(WearableInputDevice.Y_KEY)) {
+            return null;
+        }
+
+        float screenLocationX = bundle.getFloat(WearableInputDevice.X_KEY);
+        float screenLocationY = bundle.getFloat(WearableInputDevice.Y_KEY);
+
+        // Get the screen size for the locationZone
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Point screenSize = new Point();
+        wm.getDefaultDisplay().getSize(screenSize);
+
+        if (isLeftyModeEnabled(context)) {
+            // By default, the rotated placement is exactly the opposite.
+            // This may be overridden if there is a remapping of buttons applied as well.
+            float screenRotatedX = screenSize.x - screenLocationX;
+            float screenRotatedY = screenSize.y - screenLocationY;
+
+            if (bundle.containsKey(X_KEY_ROTATED) && bundle.containsKey(Y_KEY_ROTATED)) {
+                screenRotatedX = bundle.getFloat(X_KEY_ROTATED);
+                screenRotatedY = bundle.getFloat(Y_KEY_ROTATED);
+            }
+
+            screenLocationX = screenRotatedX;
+            screenLocationY = screenRotatedY;
+        }
+
+        boolean isRound = context.getResources().getConfiguration().isScreenRound();
+
+        ButtonInfo info =
+                new ButtonInfo(
+                        keycode,
+                        screenLocationX,
+                        screenLocationY,
+                        getLocationZone(isRound, screenSize, screenLocationX, screenLocationY));
+
+        return info;
+    }
+
+    /**
+     * Get the number of hardware buttons available. This function only works on API level 24 or
+     * higher (Wear 2.0). This count includes the primary stem key as well as any secondary stem
+     * keys available.
+     *
+     * @param context The context of the current activity
+     * @return The number of buttons available or -1 if not a Wear 2.0 device.
+     */
+    public static int getButtonCount(@NonNull Context context) {
+        if (sButtonCount == -1) {
+            int[] buttonCodes = sButtonsProvider.getAvailableButtonKeyCodes(context);
+
+            if (buttonCodes == null) {
+                return -1;
+            }
+
+            sButtonCount = buttonCodes.length;
+        }
+
+        return sButtonCount;
+    }
+
+    /**
+     * Returns an icon that can be used to represent the location of a button.
+     *
+     * @param context The context of the current activity
+     * @param keycode The keycode associated with the hardware button of interest
+     * @return A drawable representing the location of a button, or null if unavailable
+     */
+    @Nullable
+    public static Drawable getButtonIcon(@NonNull Context context, int keycode) {
+        ButtonInfo info = getButtonInfo(context, keycode);
+        if (info == null) {
+            return null;
+        }
+        return getButtonIconFromLocationZone(context, info.getLocationZone());
+    }
+
+    @VisibleForTesting
+    static RotateDrawable getButtonIconFromLocationZone(Context context, int locationZone) {
+        // To save memory for assets, we are using 4 icons to represent the 20+ possible
+        // configurations.  These 4 base icons can be rotated to fit any configuration needed.
+        // id is the drawable id for the base icon
+        // degrees is the number of degrees the icon needs to be rotated to match the wanted
+        // position
+        int id;
+        int degrees;
+
+        switch (locationZone) {
+                // Round constants
+            case LOC_EAST:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = 0;
+                break;
+            case LOC_ENE:
+            case LOC_NE:
+            case LOC_NNE:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = -45;
+                break;
+            case LOC_NORTH:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = -90;
+                break;
+            case LOC_NNW:
+            case LOC_NW:
+            case LOC_WNW:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = -135;
+                break;
+            case LOC_WEST:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = 180;
+                break;
+            case LOC_WSW:
+            case LOC_SW:
+            case LOC_SSW:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = 135;
+                break;
+            case LOC_SOUTH:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = 90;
+                break;
+            case LOC_SSE:
+            case LOC_SE:
+            case LOC_ESE:
+                id = R.drawable.ic_cc_settings_button_e;
+                degrees = 45;
+                break;
+
+                // Rectangular constants
+            case LOC_LEFT_TOP:
+                id = R.drawable.ic_cc_settings_button_bottom;
+                degrees = 180;
+                break;
+            case LOC_LEFT_CENTER:
+                id = R.drawable.ic_cc_settings_button_center;
+                degrees = 180;
+                break;
+            case LOC_LEFT_BOTTOM:
+                id = R.drawable.ic_cc_settings_button_top;
+                degrees = 180;
+                break;
+            case LOC_RIGHT_TOP:
+                id = R.drawable.ic_cc_settings_button_top;
+                degrees = 0;
+                break;
+            case LOC_RIGHT_CENTER:
+                id = R.drawable.ic_cc_settings_button_center;
+                degrees = 0;
+                break;
+            case LOC_RIGHT_BOTTOM:
+                id = R.drawable.ic_cc_settings_button_bottom;
+                degrees = 0;
+                break;
+            case LOC_TOP_LEFT:
+                id = R.drawable.ic_cc_settings_button_top;
+                degrees = -90;
+                break;
+            case LOC_TOP_CENTER:
+                id = R.drawable.ic_cc_settings_button_center;
+                degrees = -90;
+                break;
+            case LOC_TOP_RIGHT:
+                id = R.drawable.ic_cc_settings_button_bottom;
+                degrees = -90;
+                break;
+            case LOC_BOTTOM_LEFT:
+                id = R.drawable.ic_cc_settings_button_bottom;
+                degrees = 90;
+                break;
+            case LOC_BOTTOM_CENTER:
+                id = R.drawable.ic_cc_settings_button_center;
+                degrees = 90;
+                break;
+            case LOC_BOTTOM_RIGHT:
+                id = R.drawable.ic_cc_settings_button_top;
+                degrees = 90;
+                break;
+            default:
+                throw new IllegalArgumentException("Unexpected location zone");
+        }
+        RotateDrawable rotateIcon = new RotateDrawable();
+        rotateIcon.setDrawable(context.getDrawable(id));
+        rotateIcon.setFromDegrees(degrees);
+        rotateIcon.setToDegrees(degrees);
+        rotateIcon.setLevel(1);
+        return rotateIcon;
+    }
+
+    /**
+     * Returns a CharSequence that describes the placement location of a button. An example might be
+     * "Top right" or "Bottom".
+     *
+     * @param context The context of the current activity
+     * @param keycode The keycode associated with the hardware button of interest
+     * @return A CharSequence describing the placement location of the button
+     */
+    @NonNull
+    public static CharSequence getButtonLabel(@NonNull Context context, int keycode) {
+        // 4 length array where the index uses the standard quadrant counting system (minus 1 for
+        // 0 index)
+        int[] buttonsInQuadrantCount = new int[4];
+
+        // Retrieve ButtonInfo objects and count how many buttons are in a quadrant.  This is only
+        // needed for round devices but will help us come up with friendly strings to show to the
+        // user.
+        // TODO(ahugh): We can cache quadrant counts to optimize. These values should be static for
+        // each
+        // device.
+        int[] buttonCodes = sButtonsProvider.getAvailableButtonKeyCodes(context);
+
+        if (buttonCodes == null) {
+            return null;
+        }
+
+        for (int key : buttonCodes) {
+            ButtonInfo info = getButtonInfo(context, key);
+
+            if (info != null) {
+                int quadrantIndex = getQuadrantIndex(info.getLocationZone());
+                if (quadrantIndex != -1) {
+                    ++buttonsInQuadrantCount[quadrantIndex];
+                }
+            }
+        }
+
+        ButtonInfo info = getButtonInfo(context, keycode);
+        int quadrantIndex = (info != null ? getQuadrantIndex(info.getLocationZone()) : -1);
+        return info == null
+                ? null
+                : context.getString(
+                        getFriendlyLocationZoneStringId(
+                                info.getLocationZone(),
+                                (quadrantIndex == -1 ? 0 : buttonsInQuadrantCount[quadrantIndex])));
+    }
+
+    /**
+     * Returns quadrant index if locationZone is for a round device. Follows the conventional
+     * quadrant system with the top right quadrant being 0, incrementing the index by 1 going
+     * counter-clockwise around.
+     */
+    private static int getQuadrantIndex(int locationZone) {
+        switch (locationZone) {
+            case LOC_ENE:
+            case LOC_NE:
+            case LOC_NNE:
+                return 0;
+            case LOC_NNW:
+            case LOC_NW:
+            case LOC_WNW:
+                return 1;
+            case LOC_WSW:
+            case LOC_SW:
+            case LOC_SSW:
+                return 2;
+            case LOC_SSE:
+            case LOC_SE:
+            case LOC_ESE:
+                return 3;
+
+            default:
+                return -1;
+        }
+    }
+
+    /**
+     * If the screen is round, there is special logic we use to determine the string that should
+     * show on the screen. Simple strings are broad descriptors like "top right". Detailed strings
+     * are narrow descriptors like, "top right, upper" 1) If there are exactly 2 buttons in a
+     * quadrant, use detailed strings to describe button locations. 2) Otherwise, use simple strings
+     * to describe the button locations.
+     *
+     * @param locationZone The location zone to get a string id for
+     * @param buttonsInQuadrantCount The number of buttons in the quadrant of the button
+     * @return The string id to use to represent this button zone
+     */
+    @VisibleForTesting
+    static int getFriendlyLocationZoneStringId(int locationZone, int buttonsInQuadrantCount) {
+        if (buttonsInQuadrantCount == 2) {
+            switch (locationZone) {
+                case LOC_ENE:
+                    return R.string.buttons_round_top_right_lower;
+                case LOC_NE:
+                case LOC_NNE:
+                    return R.string.buttons_round_top_right_upper;
+                case LOC_NNW:
+                case LOC_NW:
+                    return R.string.buttons_round_top_left_upper;
+                case LOC_WNW:
+                    return R.string.buttons_round_top_left_lower;
+                case LOC_ESE:
+                case LOC_SE:
+                    return R.string.buttons_round_bottom_left_upper;
+                case LOC_SSE:
+                    return R.string.buttons_round_bottom_left_lower;
+                case LOC_SSW:
+                    return R.string.buttons_round_bottom_right_lower;
+                case LOC_SW:
+                case LOC_WSW:
+                    return R.string.buttons_round_bottom_right_upper;
+                default: // fall out
+            }
+        }
+
+        // If we couldn't find a detailed string, or we need a simple string
+        switch (locationZone) {
+                // Round constants
+            case LOC_EAST:
+                return R.string.buttons_round_center_right;
+            case LOC_ENE:
+            case LOC_NE:
+            case LOC_NNE:
+                return R.string.buttons_round_top_right;
+            case LOC_NORTH:
+                return R.string.buttons_round_top_center;
+            case LOC_NNW:
+            case LOC_NW:
+            case LOC_WNW:
+                return R.string.buttons_round_top_left;
+            case LOC_WEST:
+                return R.string.buttons_round_center_left;
+            case LOC_WSW:
+            case LOC_SW:
+            case LOC_SSW:
+                return R.string.buttons_round_bottom_left;
+            case LOC_SOUTH:
+                return R.string.buttons_round_bottom_center;
+            case LOC_SSE:
+            case LOC_SE:
+            case LOC_ESE:
+                return R.string.buttons_round_bottom_right;
+
+                // Rectangular constants
+            case LOC_LEFT_TOP:
+                return R.string.buttons_rect_left_top;
+            case LOC_LEFT_CENTER:
+                return R.string.buttons_rect_left_center;
+            case LOC_LEFT_BOTTOM:
+                return R.string.buttons_rect_left_bottom;
+            case LOC_RIGHT_TOP:
+                return R.string.buttons_rect_right_top;
+            case LOC_RIGHT_CENTER:
+                return R.string.buttons_rect_right_center;
+            case LOC_RIGHT_BOTTOM:
+                return R.string.buttons_rect_right_bottom;
+            case LOC_TOP_LEFT:
+                return R.string.buttons_rect_top_left;
+            case LOC_TOP_CENTER:
+                return R.string.buttons_rect_top_center;
+            case LOC_TOP_RIGHT:
+                return R.string.buttons_rect_top_right;
+            case LOC_BOTTOM_LEFT:
+                return R.string.buttons_rect_bottom_left;
+            case LOC_BOTTOM_CENTER:
+                return R.string.buttons_rect_bottom_center;
+            case LOC_BOTTOM_RIGHT:
+                return R.string.buttons_rect_bottom_right;
+            default:
+                throw new IllegalArgumentException("Unexpected location zone");
+        }
+    }
+
+    /**
+     * For round devices, the location zone is defined using 16 points in a compass arrangement. If
+     * a button falls between anchor points, this method will return the closest anchor.
+     *
+     * <p>For rectangular devices, the location zone is defined by splitting each side into thirds.
+     * If a button falls anywhere within a zone, the method will return that zone. The constants for
+     * these zones are named LOC_[side in question]_[which third is affected]. E.g. LOC_TOP_RIGHT
+     * would refer to the right third of the top side of the device.
+     */
+    @VisibleForTesting
+    /* package */ static int getLocationZone(
+            boolean isRound, Point screenSize, float screenLocationX, float screenLocationY) {
+        if (screenLocationX == Float.MAX_VALUE || screenLocationY == Float.MAX_VALUE) {
+            return LOC_UNKNOWN;
+        }
+
+        return isRound
+                ? getLocationZoneRound(screenSize, screenLocationX, screenLocationY)
+                : getLocationZoneRectangular(screenSize, screenLocationX, screenLocationY);
+    }
+
+    private static int getLocationZoneRound(
+            Point screenSize, float screenLocationX, float screenLocationY) {
+        // Convert screen coordinate to Cartesian coordinate
+        float cartesianX = screenLocationX - screenSize.x / 2;
+        float cartesianY = screenSize.y / 2 - screenLocationY;
+
+        // Use polar coordinates to figure out which zone the point is in
+        double angle = Math.atan2(cartesianY, cartesianX);
+
+        // Convert angle to all positive values
+        if (angle < 0) {
+            angle += 2 * Math.PI;
+        }
+
+        // Return the associated section rounded to the nearest anchor.
+        // Using some clever math tricks and enum declaration, we can reduce this calculation
+        // down to a single formula that converts angle to enum value.
+        return Math.round((float) (angle / (Math.PI / 8))) % LOC_ROUND_COUNT;
+    }
+
+    private static int getLocationZoneRectangular(
+            Point screenSize, float screenLocationX, float screenLocationY) {
+        // Calculate distance to each edge.
+        float deltaFromLeft = screenLocationX;
+        float deltaFromRight = screenSize.x - screenLocationX;
+        float deltaFromTop = screenLocationY;
+        float deltaFromBottom = screenSize.y - screenLocationY;
+        float minDelta =
+                Math.min(
+                        deltaFromLeft,
+                        Math.min(deltaFromRight, Math.min(deltaFromTop, deltaFromBottom)));
+
+        // Prioritize ties to left and right sides of watch since they're more likely to be placed
+        // on the side. Buttons directly on the corner are not accounted for with this API.
+        if (minDelta == deltaFromLeft) {
+            // Left is the primary side
+            switch (whichThird(screenSize.y, screenLocationY)) {
+                case 0:
+                    return LOC_LEFT_TOP;
+                case 1:
+                    return LOC_LEFT_CENTER;
+                default:
+                    return LOC_LEFT_BOTTOM;
+            }
+        } else if (minDelta == deltaFromRight) {
+            // Right is primary side
+            switch (whichThird(screenSize.y, screenLocationY)) {
+                case 0:
+                    return LOC_RIGHT_TOP;
+                case 1:
+                    return LOC_RIGHT_CENTER;
+                default:
+                    return LOC_RIGHT_BOTTOM;
+            }
+        } else if (minDelta == deltaFromTop) {
+            // Top is primary side
+            switch (whichThird(screenSize.x, screenLocationX)) {
+                case 0:
+                    return LOC_TOP_LEFT;
+                case 1:
+                    return LOC_TOP_CENTER;
+                default:
+                    return LOC_TOP_RIGHT;
+            }
+        } else /* if (minDelta == deltaFromBottom) */ {
+            // Bottom is primary side
+            switch (whichThird(screenSize.x, screenLocationX)) {
+                case 0:
+                    return LOC_BOTTOM_LEFT;
+                case 1:
+                    return LOC_BOTTOM_CENTER;
+                default:
+                    return LOC_BOTTOM_RIGHT;
+            }
+        }
+    }
+
+    // Returns 0, 1, or 2 which correspond to the index of the third the screen point lies in
+    // from 'left to right' or 'top to bottom'.
+    private static int whichThird(float screenLength, float screenLocation) {
+        if (screenLocation <= screenLength / 3) {
+            return 0;
+        } else if (screenLocation <= screenLength * 2 / 3) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    private static boolean isLeftyModeEnabled(Context context) {
+        return Settings.System.getInt(
+                        context.getContentResolver(),
+                        Settings.System.USER_ROTATION,
+                        Surface.ROTATION_0)
+                == Surface.ROTATION_180;
+    }
+
+    /** Metadata for a specific button. */
+    public static final class ButtonInfo {
+        private final int mKeycode;
+        private final float mX;
+        private final float mY;
+
+        /**
+         * The location zone of the button as defined in the {@link #getButtonInfo(Context, int)}
+         * method. The intended use is to help developers attach a friendly String to the button
+         * location. This value is LOC_UNKNOWN if the information is not available.
+         */
+        private final int mLocationZone;
+
+        /**
+         * Gets the keycode this {@code ButtonInfo} provides information for.
+         *
+         * @return The keycode this {@code ButtonInfo} provides information for
+         */
+        public int getKeycode() {
+            return mKeycode;
+        }
+
+        /** The x coordinate of the button in screen coordinates. */
+        public float getX() {
+            return mX;
+        }
+
+        /** The y coordinate of the button in screen coordinates. */
+        public float getY() {
+            return mY;
+        }
+
+        /** The location zone of the button (e.g. LOC_EAST) */
+        public int getLocationZone() {
+            return mLocationZone;
+        }
+
+        /** @hide */
+        @RestrictTo(RestrictTo.Scope.LIBRARY)
+        @VisibleForTesting
+        public ButtonInfo(int keycode, float x, float y, int locationZone) {
+            this.mKeycode = keycode;
+            this.mX = x;
+            this.mY = y;
+            this.mLocationZone = locationZone;
+        }
+    }
+}
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/WearableButtonsProvider.java b/wear/wear-input/src/main/java/androidx/wear/input/WearableButtonsProvider.java
new file mode 100644
index 0000000..5a68920
--- /dev/null
+++ b/wear/wear-input/src/main/java/androidx/wear/input/WearableButtonsProvider.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.wear.input;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * A provider interface to allow {@link WearableButtons} to query for information on the device's
+ * buttons from the platform. This exists to allow for the button provider to be switched out for
+ * testing, for example, by using {@link androidx.wear.input.testing.TestWearableButtonsProvider}.
+ */
+public interface WearableButtonsProvider {
+    /**
+     * Returns a bundle containing the metadata of a specific button. Currently, only location is
+     * supported. Use with {@link com.google.android.wearable.input.WearableInputDevice#X_KEY} and
+     * {@link com.google.android.wearable.input.WearableInputDevice#Y_KEY}. The key will not be
+     * present if the information is not available for the requested keycode.
+     *
+     * <p>The location returned is a Cartesian coordinate where the bottom left corner of the screen
+     * is the origin. The unit of measurement is in pixels. The coordinates do not take rotation
+     * into account and assume that the device is in the standard upright position.
+     *
+     * @param context The context of the current activity
+     * @param keycode The keycode associated with the hardware button of interest
+     * @return A {@link Bundle} containing the metadata for the given keycode
+     */
+    @NonNull
+    Bundle getButtonInfo(@NonNull Context context, int keycode);
+
+    /**
+     * Get the keycodes of available hardware buttons on device. This function based on key's
+     * locations from system property. This count includes the primary stem key as well as any
+     * secondary stem keys available.
+     *
+     * @param context The context of the current activity
+     * @return An int array of available button keycodes, or null if no keycodes could be read.
+     */
+    @Nullable
+    int[] getAvailableButtonKeyCodes(@NonNull Context context);
+}
diff --git a/wear/wear-input/src/main/res/color/button_icon_color.xml b/wear/wear-input/src/main/res/color/button_icon_color.xml
new file mode 100644
index 0000000..cc6e02b
--- /dev/null
+++ b/wear/wear-input/src/main/res/color/button_icon_color.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/textColorPrimary" android:state_enabled="true" />
+    <item android:color="?android:colorButtonNormal" android:state_enabled="false" />
+</selector>
diff --git a/wear/wear-input/src/main/res/drawable/action_item_background.xml b/wear/wear-input/src/main/res/drawable/action_item_background.xml
new file mode 100644
index 0000000..22d254d
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/action_item_background.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <color android:color="?android:attr/colorControlHighlight" />
+    </item>
+</ripple>
diff --git a/wear/wear-input/src/main/res/drawable/action_item_icon_background.xml b/wear/wear-input/src/main/res/drawable/action_item_icon_background.xml
new file mode 100644
index 0000000..b10a515
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/action_item_icon_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+  <solid android:color="?android:attr/colorForeground"/>
+</shape>
diff --git a/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_bottom.xml b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_bottom.xml
new file mode 100644
index 0000000..cdbb37a
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_bottom.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="24dp"
+  android:height="24dp"
+  android:tint="@color/button_icon_color"
+  android:viewportHeight="24.0"
+  android:viewportWidth="24.0">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M20.8,19.1V4.9C20.8,3.8 20,3 18.9,3H4.7C3.6,3 2.8,3.8 2.8,4.9v14.1c0,1.1 0.8,1.9 1.9,1.9h14.1C20,21 20.8,20.2 20.8,19.1zM18.9,19.1H4.7V4.9h14.1V19.1z" />
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M24,15.9v2.6c0,0.4 -0.3,0.6 -0.6,0.6h-1.3v-3.9h1.3C23.7,15.2 24,15.5 24,15.9z" />
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_center.xml b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_center.xml
new file mode 100644
index 0000000..364c77d
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_center.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="24dp"
+  android:height="24dp"
+  android:tint="@color/button_icon_color"
+  android:viewportHeight="24.0"
+  android:viewportWidth="24.0">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M18.9,3H4.7C3.6,3 2.8,3.8 2.8,4.9v14.1c0,1.1 0.8,1.9 1.9,1.9h14.1c1.1,0 1.9,-0.8 1.9,-1.9V4.9C20.8,3.8 20,3 18.9,3zM18.9,19.1H4.7V4.9h14.1V19.1z" />
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M23.4,14h-1.3v-3.9h1.3c0.4,0 0.6,0.3 0.6,0.6v2.6C24,13.7 23.7,14 23.4,14z" />
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_e.xml b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_e.xml
new file mode 100644
index 0000000..df85799
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_e.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="24dp"
+  android:height="24dp"
+  android:tint="@color/button_icon_color"
+  android:viewportHeight="24.0"
+  android:viewportWidth="24.0">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M12,21c5,0 9,-4 9,-9s-4,-9 -9,-9c-5,0 -9,4 -9,9S7,21 12,21zM12,5c3.9,0 7,3.1 7,7s-3.1,7 -7,7s-7,-3.1 -7,-7S8.1,5 12,5z" />
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M22.2,9H24v6h-1.8V9z" />
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_top.xml b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_top.xml
new file mode 100644
index 0000000..cc5c342
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_cc_settings_button_top.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="24dp"
+  android:height="24dp"
+  android:tint="@color/button_icon_color"
+  android:viewportHeight="24.0"
+  android:viewportWidth="24.0">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M18.9,3H4.7C3.6,3 2.8,3.8 2.8,4.9v14.1c0,1.1 0.8,1.9 1.9,1.9h14.1c1.1,0 1.9,-0.8 1.9,-1.9V4.9C20.8,3.8 20,3 18.9,3zM18.9,19.1H4.7V4.9h14.1V19.1z" />
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M23.4,8.8h-1.3V4.9h1.3c0.4,0 0.6,0.3 0.6,0.6v2.6C24,8.5 23.7,8.8 23.4,8.8z" />
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_expand_less_white_22.xml b/wear/wear-input/src/main/res/drawable/ic_expand_less_white_22.xml
new file mode 100644
index 0000000..2dbcf36
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_expand_less_white_22.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="22dp"
+        android:height="22dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12,8l-6,6 1.41,1.41L12,10.83l4.59,4.58L18,14z"/>
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_more_horiz_24dp_wht.xml b/wear/wear-input/src/main/res/drawable/ic_more_horiz_24dp_wht.xml
new file mode 100644
index 0000000..723b606
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_more_horiz_24dp_wht.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/ic_more_vert_24dp_wht.xml b/wear/wear-input/src/main/res/drawable/ic_more_vert_24dp_wht.xml
new file mode 100644
index 0000000..fbb5018
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/ic_more_vert_24dp_wht.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#ffffffff"
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/wear/wear-input/src/main/res/drawable/preference_wrapped_icon.xml b/wear/wear-input/src/main/res/drawable/preference_wrapped_icon.xml
new file mode 100644
index 0000000..789d5ee
--- /dev/null
+++ b/wear/wear-input/src/main/res/drawable/preference_wrapped_icon.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:tools="http://schemas.android.com/tools">
+
+  <item>
+    <shape android:shape="oval" android:tint="?android:colorPrimary">
+      <solid android:color="@android:color/white" />
+      <size android:width="40dp" android:height="40dp" />
+    </shape>
+  </item>
+  <item
+      android:id="@+id/nested_icon"
+      android:drawable="@android:color/transparent"
+      android:height="24dp"
+      android:width="24dp"
+      android:gravity="center" />
+</layer-list>
diff --git a/wear/wear-input/src/main/res/values/color.xml b/wear/wear-input/src/main/res/values/color.xml
new file mode 100644
index 0000000..cdac867
--- /dev/null
+++ b/wear/wear-input/src/main/res/values/color.xml
@@ -0,0 +1,65 @@
+<resources>
+    <color name="white">@android:color/white</color>
+    <color name="black">@android:color/black</color>
+
+    <!-- Blue A400 -->
+    <color name="blue_a400">#2979FF</color>
+    <!-- Blue 800 -->
+    <color name="dark_blue">#1565C0</color>
+    <!-- Green A700 -->
+    <color name="green">#00C853</color>
+    <!-- Grey 400 -->
+    <color name="light_grey">#bdbdbd</color>
+    <!-- Grey 600 -->
+    <color name="grey">#757575</color>
+    <!-- Grey 800 -->
+    <color name="dark_grey">#424242</color>
+    <!-- Red A200 -->
+    <color name="red_a200">#FF5252</color>
+    <!-- Red 700 -->
+    <color name="dark_red">#D32F2F</color>
+    <!-- Amber 900 -->
+    <color name="orange">#FF6D3F</color>
+
+    <color name="semitransparent_grey">#66777777</color>
+
+    <color name="dismiss_overlay_bg">#80000000</color>
+    <color name="dismiss_close">#FF5151</color>
+    <color name="dismiss_close_pressed">#B83120</color>
+
+    <!-- Light Blue 700 -->
+    <color name="circular_button_normal">#0288D1</color>
+    <!-- Light Blue 900 -->
+    <color name="circular_button_pressed">#01579B</color>
+    <color name="circular_button_disabled">@color/grey</color>
+    <color name="primary_text_light">@color/dark_grey</color>
+    <!-- Grey 500 -->
+    <color name="secondary_text_light">#9E9E9E</color>
+    <!-- Grey 300 -->
+    <color name="disabled_text_light">#E0E0E0</color>
+
+    <color name="primary_text_dark">@color/white</color>
+    <color name="ambient_mode_text">@color/primary_text_dark</color>
+    <!-- Grey 300 -->
+    <color name="card_default_background">#E0E0E0</color>
+
+    <!-- 86% Black -->
+    <color name="black_86p">#DE000000</color>
+    <!-- 54% Black -->
+    <color name="black_54p">#8A000000</color>
+
+    <!-- 30% Black -->
+    <color name="action_button_background">#4D000000</color>
+
+    <color name="dialog_background">#414141</color>
+    <color name="dialog_shade_background">#606060</color>
+
+    <!-- Default colors to be used by the spinner if none are provided -->
+    <array name="progress_spinner_sequence">
+        <item>#FFF4B400</item>
+        <item>#FFDB4437</item>
+        <item>#FF4285F4</item>
+        <item>#FF0F9D58</item>
+    </array>
+
+</resources>
diff --git a/wear/wear-input/src/main/res/values/strings.xml b/wear/wear-input/src/main/res/values/strings.xml
new file mode 100644
index 0000000..4536847
--- /dev/null
+++ b/wear/wear-input/src/main/res/values/strings.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- String describing a button location on a round device when the button is in the top center position [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_center">Top</string>
+    <!-- String describing a button location on a round device when the button is in the top right position [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_right">Top right</string>
+    <!-- String describing a button location on a round device when the button is in the center right position [CHAR LIMIT=35] -->
+    <string name="buttons_round_center_right">Center right</string>
+    <!-- String describing a button location on a round device when the button is in the bottom right position [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_right">Bottom right</string>
+    <!-- String describing a button location on a round device when the button is in the bottom center position [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_center">Bottom</string>
+    <!-- String describing a button location on a round device when the button is in the bottom left position [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_left">Bottom left</string>
+    <!-- String describing a button location on a round device when the button is in the center left position [CHAR LIMIT=35] -->
+    <string name="buttons_round_center_left">Center left</string>
+    <!-- String describing a button location on a round device when the button is in the top left position [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_left">Top left</string>
+    <!-- String describing a button location on a round device when the button between 12 o'clock and halfway between 1 and 2 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_right_upper">Top right, upper</string>
+    <!-- String describing a button location on a round device when the button between halfway between 1 and 2 o'clock and 3 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_right_lower">Top right, lower</string>
+    <!-- String describing a button location on a round device when the button between 3 o'clock and halfway between 4 and 5 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_right_upper">Bottom right, upper</string>
+    <!-- String describing a button location on a round device when the button between halfway between 4 and 5 o'clock and 6 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_right_lower">Bottom right, lower</string>
+    <!-- String describing a button location on a round device when the button between 6 o'clock and halfway between 7 and 8 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_left_lower">Bottom left, lower</string>
+    <!-- String describing a button location on a round device when the button between halfway between 7 and 8 o'clock and 9 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_bottom_left_upper">Bottom left, upper</string>
+    <!-- String describing a button location on a round device when the button between 9 o'clock and halfway between 10 and 11 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_left_lower">Top left, lower</string>
+    <!-- String describing a button location on a round device when the button between halfway between 10 and 11 o'clock and 12 o'clock [CHAR LIMIT=35] -->
+    <string name="buttons_round_top_left_upper">Top left, upper</string>
+    <!-- String describing a button location on a square device when the button is on the left side near the top corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_left_top">Top, left side</string>
+    <!-- String describing a button location on a square device when the button is on the left side near the center [CHAR LIMIT=35] -->
+    <string name="buttons_rect_left_center">Center left</string>
+    <!-- String describing a button location on a square device when the button is on the left side near the bottom corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_left_bottom">Bottom, left side</string>
+    <!-- String describing a button location on a square device when the button is on the right side near the top corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_right_top">Top, right side</string>
+    <!-- String describing a button location on a square device when the button is on the right side near the center [CHAR LIMIT=35] -->
+    <string name="buttons_rect_right_center">Center right</string>
+    <!-- String describing a button location on a square device when the button is on the right side near the bottom corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_right_bottom">Bottom, right side</string>
+    <!-- String describing a button location on a square device when the button is on the top side near the left corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_top_left">Top left</string>
+    <!-- String describing a button location on a square device when the button is on the top side near the center [CHAR LIMIT=35] -->
+    <string name="buttons_rect_top_center">Top</string>
+    <!-- String describing a button location on a square device when the button is on the top side near the right corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_top_right">Top right</string>
+    <!-- String describing a button location on a square device when the button is on the bottom side near the left corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_bottom_left">Bottom left</string>
+    <!-- String describing a button location on a square device when the button is on the bottom side near the center [CHAR LIMIT=35] -->
+    <string name="buttons_rect_bottom_center">Bottom</string>
+    <!-- String describing a button location on a square device when the button is on the bottom side near the right corner [CHAR LIMIT=35] -->
+    <string name="buttons_rect_bottom_right">Bottom right</string>
+</resources>
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java b/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java
new file mode 100644
index 0000000..99b4c4a
--- /dev/null
+++ b/wear/wear-input/src/test/java/androidx/wear/input/WearableButtonsTest.java
@@ -0,0 +1,341 @@
+/*
+ * 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.wear.input;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.drawable.RotateDrawable;
+import android.os.Build;
+import android.provider.Settings;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.wear.R;
+import androidx.wear.input.testing.TestWearableButtonsProvider;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.internal.DoNotInstrument;
+import org.robolectric.shadows.ShadowDrawable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Unit tests for {@link WearableButtons}. */
+@RunWith(RobolectricTestRunner.class)
+@DoNotInstrument
+@Config(sdk = Build.VERSION_CODES.P)
+public class WearableButtonsTest {
+    private final Point mScreenSize = new Point(480, 480);
+
+    @Test
+    public void testExactPoints_round() {
+        // Positions were calculated using the following formula:
+        // ScreenCoordinate.x = r*(1+cos(a))
+        // ScreenCoordinate.y = r*(1-sin(a))
+        // Angle = pi/8 * N, where N was the cardinal position
+        // r = 240 because the screen is 480x480
+        // Wolfram Alpha was helpful:  x=240*(1+cos(a)), y=240*(1-sin(a)), a=pi/8.0
+
+        assertEquals(
+                WearableButtons.LOC_EAST,
+                WearableButtons.getLocationZone(true, mScreenSize, 480, 240));
+        assertEquals(
+                WearableButtons.LOC_ENE,
+                WearableButtons.getLocationZone(true, mScreenSize, 461.731f, 148.156f));
+        assertEquals(
+                WearableButtons.LOC_NE,
+                WearableButtons.getLocationZone(true, mScreenSize, 409.706f, 70.294f));
+        assertEquals(
+                WearableButtons.LOC_NNE,
+                WearableButtons.getLocationZone(true, mScreenSize, 331.844f, 18.269f));
+        assertEquals(
+                WearableButtons.LOC_NORTH,
+                WearableButtons.getLocationZone(true, mScreenSize, 240, 0));
+        assertEquals(
+                WearableButtons.LOC_NNW,
+                WearableButtons.getLocationZone(true, mScreenSize, 148.156f, 18.269f));
+        assertEquals(
+                WearableButtons.LOC_NW,
+                WearableButtons.getLocationZone(true, mScreenSize, 70.294f, 70.294f));
+        assertEquals(
+                WearableButtons.LOC_WNW,
+                WearableButtons.getLocationZone(true, mScreenSize, 18.269f, 148.156f));
+        assertEquals(
+                WearableButtons.LOC_WEST,
+                WearableButtons.getLocationZone(true, mScreenSize, 0, 240));
+        assertEquals(
+                WearableButtons.LOC_WSW,
+                WearableButtons.getLocationZone(true, mScreenSize, 18.269f, 331.844f));
+        assertEquals(
+                WearableButtons.LOC_SW,
+                WearableButtons.getLocationZone(true, mScreenSize, 70.294f, 409.706f));
+        assertEquals(
+                WearableButtons.LOC_SSW,
+                WearableButtons.getLocationZone(true, mScreenSize, 148.156f, 461.731f));
+        assertEquals(
+                WearableButtons.LOC_SOUTH,
+                WearableButtons.getLocationZone(true, mScreenSize, 240, 480));
+        assertEquals(
+                WearableButtons.LOC_SSE,
+                WearableButtons.getLocationZone(true, mScreenSize, 331.844f, 461.731f));
+        assertEquals(
+                WearableButtons.LOC_SE,
+                WearableButtons.getLocationZone(true, mScreenSize, 409.706f, 409.706f));
+        assertEquals(
+                WearableButtons.LOC_ESE,
+                WearableButtons.getLocationZone(true, mScreenSize, 461.731f, 331.844f));
+    }
+
+    @Test
+    public void testNonExactPoints_round() {
+        // Positions were randomly determined based on #testExactPoints calculations
+        // 1 degree in radians = Math.PI / 180;
+        // Using formula from #testExactPoints, add and subtract X degrees from each exact point and
+        // test edge cases
+        // Wolfram Alpha helps again:  x = 240*(1+cos(a)), y=240*(1-sin(a)), a=(15.0*pi/8.0)+pi/180
+
+        // Exact +1 degree
+        assertEquals(
+                WearableButtons.LOC_ESE,
+                WearableButtons.getLocationZone(true, mScreenSize, 463.3f, 327.96f));
+        // Exact -1 degree
+        assertEquals(
+                WearableButtons.LOC_ESE,
+                WearableButtons.getLocationZone(true, mScreenSize, 460.094f, 335.7f));
+
+        // Exact +5 degrees
+        assertEquals(
+                WearableButtons.LOC_WNW,
+                WearableButtons.getLocationZone(true, mScreenSize, 16.7f, 152.04f));
+        // Exact -5 degrees
+        assertEquals(
+                WearableButtons.LOC_WNW,
+                WearableButtons.getLocationZone(true, mScreenSize, 19.906f, 144.3f));
+
+        // Exactly between SE and ESE
+        assertEquals(
+                WearableButtons.LOC_ESE,
+                WearableButtons.getLocationZone(true, mScreenSize, 439.553f, 373.337f));
+
+        // Exactly between SSE and SE
+        assertEquals(
+                WearableButtons.LOC_SE,
+                WearableButtons.getLocationZone(true, mScreenSize, 373.337f, 439.553f));
+    }
+
+    @Test
+    public void testEdgePoints_rect() {
+        assertEquals(
+                WearableButtons.LOC_LEFT_TOP,
+                WearableButtons.getLocationZone(false, mScreenSize, 0, 160));
+        assertEquals(
+                WearableButtons.LOC_LEFT_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 0, 320));
+        assertEquals(
+                WearableButtons.LOC_LEFT_BOTTOM,
+                WearableButtons.getLocationZone(false, mScreenSize, 0, 480));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_TOP,
+                WearableButtons.getLocationZone(false, mScreenSize, 480, 160));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 480, 320));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_BOTTOM,
+                WearableButtons.getLocationZone(false, mScreenSize, 480, 480));
+        assertEquals(
+                WearableButtons.LOC_TOP_LEFT,
+                WearableButtons.getLocationZone(false, mScreenSize, 160, 0));
+        assertEquals(
+                WearableButtons.LOC_TOP_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 320, 0));
+        assertEquals(
+                WearableButtons.LOC_TOP_RIGHT,
+                WearableButtons.getLocationZone(false, mScreenSize, 479, 0));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_LEFT,
+                WearableButtons.getLocationZone(false, mScreenSize, 160, 480));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 320, 480));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_RIGHT,
+                WearableButtons.getLocationZone(false, mScreenSize, 479, 480));
+    }
+
+    @Test
+    public void testNonEdgePoints_rect() {
+        assertEquals(
+                WearableButtons.LOC_LEFT_TOP,
+                WearableButtons.getLocationZone(false, mScreenSize, 50, 100));
+        assertEquals(
+                WearableButtons.LOC_LEFT_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 80, 300));
+        assertEquals(
+                WearableButtons.LOC_LEFT_BOTTOM,
+                WearableButtons.getLocationZone(false, mScreenSize, 100, 350));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_TOP,
+                WearableButtons.getLocationZone(false, mScreenSize, 460, 120));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 450, 270));
+        assertEquals(
+                WearableButtons.LOC_RIGHT_BOTTOM,
+                WearableButtons.getLocationZone(false, mScreenSize, 430, 400));
+        assertEquals(
+                WearableButtons.LOC_TOP_LEFT,
+                WearableButtons.getLocationZone(false, mScreenSize, 130, 20));
+        assertEquals(
+                WearableButtons.LOC_TOP_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 280, 30));
+        assertEquals(
+                WearableButtons.LOC_TOP_RIGHT,
+                WearableButtons.getLocationZone(false, mScreenSize, 429, 40));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_LEFT,
+                WearableButtons.getLocationZone(false, mScreenSize, 140, 470));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_CENTER,
+                WearableButtons.getLocationZone(false, mScreenSize, 290, 460));
+        assertEquals(
+                WearableButtons.LOC_BOTTOM_RIGHT,
+                WearableButtons.getLocationZone(false, mScreenSize, 439, 450));
+    }
+
+    @Test
+    public void testSimpleStrings() {
+        assertEquals(
+                R.string.buttons_round_bottom_right,
+                WearableButtons.getFriendlyLocationZoneStringId(WearableButtons.LOC_ESE, 1));
+        assertEquals(
+                R.string.buttons_round_bottom_left_upper,
+                WearableButtons.getFriendlyLocationZoneStringId(WearableButtons.LOC_ESE, 2));
+        assertEquals(
+                R.string.buttons_rect_bottom_left,
+                WearableButtons.getFriendlyLocationZoneStringId(
+                        WearableButtons.LOC_BOTTOM_LEFT, 1));
+        assertEquals(
+                R.string.buttons_rect_bottom_left,
+                WearableButtons.getFriendlyLocationZoneStringId(
+                        WearableButtons.LOC_BOTTOM_LEFT, 2));
+    }
+
+    @Test
+    public void testSimpleIcons() {
+        testRotateDrawable(WearableButtons.LOC_ESE, R.drawable.ic_cc_settings_button_e, 45);
+        testRotateDrawable(WearableButtons.LOC_WNW, R.drawable.ic_cc_settings_button_e, -135);
+        testRotateDrawable(
+                WearableButtons.LOC_BOTTOM_LEFT, R.drawable.ic_cc_settings_button_bottom, 90);
+        testRotateDrawable(
+                WearableButtons.LOC_TOP_CENTER, R.drawable.ic_cc_settings_button_center, -90);
+        testRotateDrawable(WearableButtons.LOC_TOP_LEFT, R.drawable.ic_cc_settings_button_top, -90);
+    }
+
+    @Test
+    public void testGetButtonsRighty() {
+        Map<Integer, TestWearableButtonsProvider.TestWearableButtonLocation> buttons =
+                new HashMap<>();
+        buttons.put(
+                KeyEvent.KEYCODE_STEM_1,
+                new TestWearableButtonsProvider.TestWearableButtonLocation(1, 2, 3, 4));
+
+        TestWearableButtonsProvider provider = new TestWearableButtonsProvider(buttons);
+        WearableButtons.setWearableButtonsProvider(provider);
+
+        setLeftyModeEnabled(false);
+        WearableButtons.ButtonInfo info =
+                WearableButtons.getButtonInfo(
+                        ApplicationProvider.getApplicationContext(), KeyEvent.KEYCODE_STEM_1);
+        assertNotNull(info);
+        assertEquals(1, info.getX(), 1.0e-7);
+        assertEquals(2, info.getY(), 1.0e-7);
+    }
+
+    @Test
+    public void testGetButtonsLefty() {
+        setLeftyModeEnabled(true);
+        Map<Integer, TestWearableButtonsProvider.TestWearableButtonLocation> buttons =
+                new HashMap<>();
+        buttons.put(
+                KeyEvent.KEYCODE_STEM_1,
+                new TestWearableButtonsProvider.TestWearableButtonLocation(1, 2, 3, 4));
+
+        TestWearableButtonsProvider provider = new TestWearableButtonsProvider(buttons);
+        WearableButtons.setWearableButtonsProvider(provider);
+        WearableButtons.ButtonInfo info =
+                WearableButtons.getButtonInfo(
+                        ApplicationProvider.getApplicationContext(), KeyEvent.KEYCODE_STEM_1);
+        assertNotNull(info);
+        assertEquals(3, info.getX(), 1.0e-7);
+        assertEquals(4, info.getY(), 1.0e-7);
+    }
+
+    @Test
+    public void testGetButtonsLeftyNoData() {
+        Context context = ApplicationProvider.getApplicationContext();
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        Shadows.shadowOf(display).setWidth(480);
+        Shadows.shadowOf(display).setHeight(480);
+
+        setLeftyModeEnabled(true);
+        Map<Integer, TestWearableButtonsProvider.TestWearableButtonLocation> buttons =
+                new HashMap<>();
+        buttons.put(
+                KeyEvent.KEYCODE_STEM_1,
+                new TestWearableButtonsProvider.TestWearableButtonLocation(1, 2));
+
+        TestWearableButtonsProvider provider = new TestWearableButtonsProvider(buttons);
+        WearableButtons.setWearableButtonsProvider(provider);
+        WearableButtons.ButtonInfo info =
+                WearableButtons.getButtonInfo(context, KeyEvent.KEYCODE_STEM_1);
+        assertNotNull(info);
+        assertEquals(479, info.getX(), 1.0e-7); // == 480 - 1
+        assertEquals(478, info.getY(), 1.0e-7); // == 480 - 2
+    }
+
+    private void testRotateDrawable(
+            int locationZone, int expectedDrawableId, int expectedDegreeRotation) {
+        RotateDrawable rotateDrawable =
+                WearableButtons.getButtonIconFromLocationZone(
+                        ApplicationProvider.getApplicationContext(), locationZone);
+
+        // We need Robolectric to pull out the underlying resource ID.
+        ShadowDrawable rotateDrawableShadow = Shadows.shadowOf(rotateDrawable.getDrawable());
+
+        assertEquals(rotateDrawableShadow.getCreatedFromResId(), expectedDrawableId);
+        assertEquals(expectedDegreeRotation, rotateDrawable.getFromDegrees(), .001);
+    }
+
+    private void setLeftyModeEnabled(boolean enabled) {
+        Settings.System.putInt(
+                ApplicationProvider.getApplicationContext().getContentResolver(),
+                Settings.System.USER_ROTATION,
+                enabled ? Surface.ROTATION_180 : Surface.ROTATION_0);
+    }
+}
diff --git a/wear/wear/build.gradle b/wear/wear/build.gradle
index 2cf341a..0ecccdf 100644
--- a/wear/wear/build.gradle
+++ b/wear/wear/build.gradle
@@ -41,6 +41,7 @@
     name = "Android Wear Support UI"
     publish = Publish.SNAPSHOT_AND_RELEASE
     mavenGroup = LibraryGroups.WEAR
+    mavenVersion = LibraryVersions.WEAR
     inceptionYear = "2016"
     description = "Android Wear Support UI"
 }
diff --git a/webkit/webkit/api/1.3.0-rc01.txt b/webkit/webkit/api/1.3.0-rc01.txt
new file mode 100644
index 0000000..57f9939
--- /dev/null
+++ b/webkit/webkit/api/1.3.0-rc01.txt
@@ -0,0 +1,270 @@
+// Signature format: 3.0
+package androidx.webkit {
+
+  public abstract class JavaScriptReplyProxy {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(String);
+  }
+
+  public final class ProxyConfig {
+    method public java.util.List<java.lang.String!> getBypassRules();
+    method public java.util.List<androidx.webkit.ProxyConfig.ProxyRule!> getProxyRules();
+    field public static final String MATCH_ALL_SCHEMES = "*";
+    field public static final String MATCH_HTTP = "http";
+    field public static final String MATCH_HTTPS = "https";
+  }
+
+  public static final class ProxyConfig.Builder {
+    ctor public ProxyConfig.Builder();
+    ctor public ProxyConfig.Builder(androidx.webkit.ProxyConfig);
+    method public androidx.webkit.ProxyConfig.Builder addBypassRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect();
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String, String);
+    method public androidx.webkit.ProxyConfig build();
+    method public androidx.webkit.ProxyConfig.Builder bypassSimpleHostnames();
+    method public androidx.webkit.ProxyConfig.Builder removeImplicitRules();
+  }
+
+  public static final class ProxyConfig.ProxyRule {
+    method public String getSchemeFilter();
+    method public String getUrl();
+  }
+
+  public abstract class ProxyController {
+    method public abstract void clearProxyOverride(java.util.concurrent.Executor, Runnable);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.PROXY_OVERRIDE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ProxyController getInstance();
+    method public abstract void setProxyOverride(androidx.webkit.ProxyConfig, java.util.concurrent.Executor, Runnable);
+  }
+
+  public abstract class SafeBrowsingResponseCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void backToSafety(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void proceed(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void showInterstitial(boolean);
+  }
+
+  public abstract class ServiceWorkerClientCompat {
+    ctor public ServiceWorkerClientCompat();
+    method @WorkerThread public abstract android.webkit.WebResourceResponse? shouldInterceptRequest(android.webkit.WebResourceRequest);
+  }
+
+  public abstract class ServiceWorkerControllerCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ServiceWorkerControllerCompat getInstance();
+    method public abstract androidx.webkit.ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings();
+    method public abstract void setServiceWorkerClient(androidx.webkit.ServiceWorkerClientCompat?);
+  }
+
+  public abstract class ServiceWorkerWebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowContentAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowFileAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getBlockNetworkLoads();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getCacheMode();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowContentAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowFileAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setBlockNetworkLoads(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setCacheMode(int);
+  }
+
+  public class TracingConfig {
+    method public java.util.List<java.lang.String!> getCustomIncludedCategories();
+    method public int getPredefinedCategories();
+    method public int getTracingMode();
+    field public static final int CATEGORIES_ALL = 1; // 0x1
+    field public static final int CATEGORIES_ANDROID_WEBVIEW = 2; // 0x2
+    field public static final int CATEGORIES_FRAME_VIEWER = 64; // 0x40
+    field public static final int CATEGORIES_INPUT_LATENCY = 8; // 0x8
+    field public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 32; // 0x20
+    field public static final int CATEGORIES_NONE = 0; // 0x0
+    field public static final int CATEGORIES_RENDERING = 16; // 0x10
+    field public static final int CATEGORIES_WEB_DEVELOPER = 4; // 0x4
+    field public static final int RECORD_CONTINUOUSLY = 1; // 0x1
+    field public static final int RECORD_UNTIL_FULL = 0; // 0x0
+  }
+
+  public static class TracingConfig.Builder {
+    ctor public TracingConfig.Builder();
+    method public androidx.webkit.TracingConfig.Builder addCategories(int...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.lang.String!...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.util.Collection<java.lang.String!>);
+    method public androidx.webkit.TracingConfig build();
+    method public androidx.webkit.TracingConfig.Builder setTracingMode(int);
+  }
+
+  public abstract class TracingController {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.TracingController getInstance();
+    method public abstract boolean isTracing();
+    method public abstract void start(androidx.webkit.TracingConfig);
+    method public abstract boolean stop(java.io.OutputStream?, java.util.concurrent.Executor);
+  }
+
+  public class WebMessageCompat {
+    ctor public WebMessageCompat(String?);
+    ctor public WebMessageCompat(String?, androidx.webkit.WebMessagePortCompat![]?);
+    method public String? getData();
+    method public androidx.webkit.WebMessagePortCompat![]? getPorts();
+  }
+
+  public abstract class WebMessagePortCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_CLOSE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void close();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(androidx.webkit.WebMessageCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(android.os.Handler?, androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+  }
+
+  public abstract static class WebMessagePortCompat.WebMessageCallbackCompat {
+    ctor public WebMessagePortCompat.WebMessageCallbackCompat();
+    method public void onMessage(androidx.webkit.WebMessagePortCompat, androidx.webkit.WebMessageCompat?);
+  }
+
+  public abstract class WebResourceErrorCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract CharSequence getDescription();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getErrorCode();
+  }
+
+  public class WebResourceRequestCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isRedirect(android.webkit.WebResourceRequest);
+  }
+
+  public class WebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDark(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDarkStrategy(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getSafeBrowsingEnabled(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setDisabledActionModeMenuItems(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDark(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDarkStrategy(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setOffscreenPreRaster(android.webkit.WebSettings, boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingEnabled(android.webkit.WebSettings, boolean);
+    field public static final int DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING = 2; // 0x2
+    field public static final int DARK_STRATEGY_USER_AGENT_DARKENING_ONLY = 0; // 0x0
+    field public static final int DARK_STRATEGY_WEB_THEME_DARKENING_ONLY = 1; // 0x1
+    field public static final int FORCE_DARK_AUTO = 1; // 0x1
+    field public static final int FORCE_DARK_OFF = 0; // 0x0
+    field public static final int FORCE_DARK_ON = 2; // 0x2
+  }
+
+  public final class WebViewAssetLoader {
+    method @WorkerThread public android.webkit.WebResourceResponse? shouldInterceptRequest(android.net.Uri);
+    field public static final String DEFAULT_DOMAIN = "appassets.androidplatform.net";
+  }
+
+  public static final class WebViewAssetLoader.AssetsPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.AssetsPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.Builder {
+    ctor public WebViewAssetLoader.Builder();
+    method public androidx.webkit.WebViewAssetLoader.Builder addPathHandler(String, androidx.webkit.WebViewAssetLoader.PathHandler);
+    method public androidx.webkit.WebViewAssetLoader build();
+    method public androidx.webkit.WebViewAssetLoader.Builder setDomain(String);
+    method public androidx.webkit.WebViewAssetLoader.Builder setHttpAllowed(boolean);
+  }
+
+  public static final class WebViewAssetLoader.InternalStoragePathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.InternalStoragePathHandler(android.content.Context, java.io.File);
+    method @WorkerThread public android.webkit.WebResourceResponse handle(String);
+  }
+
+  public static interface WebViewAssetLoader.PathHandler {
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.ResourcesPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.ResourcesPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public class WebViewClientCompat extends android.webkit.WebViewClient {
+    ctor public WebViewClientCompat();
+    method @RequiresApi(23) public final void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
+    method @RequiresApi(21) @UiThread public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, androidx.webkit.WebResourceErrorCompat);
+    method @RequiresApi(27) public final void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, android.webkit.SafeBrowsingResponse);
+    method @UiThread public void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, androidx.webkit.SafeBrowsingResponseCompat);
+  }
+
+  public class WebViewCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void addWebMessageListener(android.webkit.WebView, String, java.util.Set<java.lang.String!>, androidx.webkit.WebViewCompat.WebMessageListener);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebMessagePortCompat![] createWebMessageChannel(android.webkit.WebView);
+    method public static android.content.pm.PackageInfo? getCurrentWebViewPackage(android.content.Context);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_CHROME_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebChromeClient? getWebChromeClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebViewClient getWebViewClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_RENDERER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcess? getWebViewRenderProcess(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcessClient? getWebViewRenderProcessClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.MULTI_PROCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isMultiProcessEnabled();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.VISUAL_STATE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.POST_WEB_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void removeWebMessageListener(android.webkit.WebView, String);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_WHITELIST, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String!>, android.webkit.ValueCallback<java.lang.Boolean!>?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, java.util.concurrent.Executor, androidx.webkit.WebViewRenderProcessClient);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, androidx.webkit.WebViewRenderProcessClient?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.START_SAFE_BROWSING, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean!>?);
+  }
+
+  public static interface WebViewCompat.VisualStateCallback {
+    method @UiThread public void onComplete(long);
+  }
+
+  public static interface WebViewCompat.WebMessageListener {
+    method @UiThread public void onPostMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri, boolean, androidx.webkit.JavaScriptReplyProxy);
+  }
+
+  public class WebViewFeature {
+    method public static boolean isFeatureSupported(String);
+    field public static final String CREATE_WEB_MESSAGE_CHANNEL = "CREATE_WEB_MESSAGE_CHANNEL";
+    field public static final String DISABLED_ACTION_MODE_MENU_ITEMS = "DISABLED_ACTION_MODE_MENU_ITEMS";
+    field public static final String FORCE_DARK = "FORCE_DARK";
+    field public static final String FORCE_DARK_STRATEGY = "FORCE_DARK_STRATEGY";
+    field public static final String GET_WEB_CHROME_CLIENT = "GET_WEB_CHROME_CLIENT";
+    field public static final String GET_WEB_VIEW_CLIENT = "GET_WEB_VIEW_CLIENT";
+    field public static final String GET_WEB_VIEW_RENDERER = "GET_WEB_VIEW_RENDERER";
+    field public static final String MULTI_PROCESS = "MULTI_PROCESS";
+    field public static final String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
+    field public static final String POST_WEB_MESSAGE = "POST_WEB_MESSAGE";
+    field public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE";
+    field public static final String RECEIVE_HTTP_ERROR = "RECEIVE_HTTP_ERROR";
+    field public static final String RECEIVE_WEB_RESOURCE_ERROR = "RECEIVE_WEB_RESOURCE_ERROR";
+    field public static final String SAFE_BROWSING_ENABLE = "SAFE_BROWSING_ENABLE";
+    field public static final String SAFE_BROWSING_HIT = "SAFE_BROWSING_HIT";
+    field public static final String SAFE_BROWSING_PRIVACY_POLICY_URL = "SAFE_BROWSING_PRIVACY_POLICY_URL";
+    field public static final String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY = "SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY";
+    field public static final String SAFE_BROWSING_RESPONSE_PROCEED = "SAFE_BROWSING_RESPONSE_PROCEED";
+    field public static final String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL = "SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL";
+    field public static final String SAFE_BROWSING_WHITELIST = "SAFE_BROWSING_WHITELIST";
+    field public static final String SERVICE_WORKER_BASIC_USAGE = "SERVICE_WORKER_BASIC_USAGE";
+    field public static final String SERVICE_WORKER_BLOCK_NETWORK_LOADS = "SERVICE_WORKER_BLOCK_NETWORK_LOADS";
+    field public static final String SERVICE_WORKER_CACHE_MODE = "SERVICE_WORKER_CACHE_MODE";
+    field public static final String SERVICE_WORKER_CONTENT_ACCESS = "SERVICE_WORKER_CONTENT_ACCESS";
+    field public static final String SERVICE_WORKER_FILE_ACCESS = "SERVICE_WORKER_FILE_ACCESS";
+    field public static final String SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST = "SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST";
+    field public static final String SHOULD_OVERRIDE_WITH_REDIRECTS = "SHOULD_OVERRIDE_WITH_REDIRECTS";
+    field public static final String START_SAFE_BROWSING = "START_SAFE_BROWSING";
+    field public static final String TRACING_CONTROLLER_BASIC_USAGE = "TRACING_CONTROLLER_BASIC_USAGE";
+    field public static final String VISUAL_STATE_CALLBACK = "VISUAL_STATE_CALLBACK";
+    field public static final String WEB_MESSAGE_CALLBACK_ON_MESSAGE = "WEB_MESSAGE_CALLBACK_ON_MESSAGE";
+    field public static final String WEB_MESSAGE_LISTENER = "WEB_MESSAGE_LISTENER";
+    field public static final String WEB_MESSAGE_PORT_CLOSE = "WEB_MESSAGE_PORT_CLOSE";
+    field public static final String WEB_MESSAGE_PORT_POST_MESSAGE = "WEB_MESSAGE_PORT_POST_MESSAGE";
+    field public static final String WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK = "WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK";
+    field public static final String WEB_RESOURCE_ERROR_GET_CODE = "WEB_RESOURCE_ERROR_GET_CODE";
+    field public static final String WEB_RESOURCE_ERROR_GET_DESCRIPTION = "WEB_RESOURCE_ERROR_GET_DESCRIPTION";
+    field public static final String WEB_RESOURCE_REQUEST_IS_REDIRECT = "WEB_RESOURCE_REQUEST_IS_REDIRECT";
+    field public static final String WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE = "WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE";
+    field public static final String WEB_VIEW_RENDERER_TERMINATE = "WEB_VIEW_RENDERER_TERMINATE";
+  }
+
+  public abstract class WebViewRenderProcess {
+    ctor public WebViewRenderProcess();
+    method public abstract boolean terminate();
+  }
+
+  public abstract class WebViewRenderProcessClient {
+    ctor public WebViewRenderProcessClient();
+    method public abstract void onRenderProcessResponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+    method public abstract void onRenderProcessUnresponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+  }
+
+}
+
diff --git a/webkit/webkit/api/public_plus_experimental_1.3.0-rc01.txt b/webkit/webkit/api/public_plus_experimental_1.3.0-rc01.txt
new file mode 100644
index 0000000..57f9939
--- /dev/null
+++ b/webkit/webkit/api/public_plus_experimental_1.3.0-rc01.txt
@@ -0,0 +1,270 @@
+// Signature format: 3.0
+package androidx.webkit {
+
+  public abstract class JavaScriptReplyProxy {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(String);
+  }
+
+  public final class ProxyConfig {
+    method public java.util.List<java.lang.String!> getBypassRules();
+    method public java.util.List<androidx.webkit.ProxyConfig.ProxyRule!> getProxyRules();
+    field public static final String MATCH_ALL_SCHEMES = "*";
+    field public static final String MATCH_HTTP = "http";
+    field public static final String MATCH_HTTPS = "https";
+  }
+
+  public static final class ProxyConfig.Builder {
+    ctor public ProxyConfig.Builder();
+    ctor public ProxyConfig.Builder(androidx.webkit.ProxyConfig);
+    method public androidx.webkit.ProxyConfig.Builder addBypassRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect();
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String, String);
+    method public androidx.webkit.ProxyConfig build();
+    method public androidx.webkit.ProxyConfig.Builder bypassSimpleHostnames();
+    method public androidx.webkit.ProxyConfig.Builder removeImplicitRules();
+  }
+
+  public static final class ProxyConfig.ProxyRule {
+    method public String getSchemeFilter();
+    method public String getUrl();
+  }
+
+  public abstract class ProxyController {
+    method public abstract void clearProxyOverride(java.util.concurrent.Executor, Runnable);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.PROXY_OVERRIDE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ProxyController getInstance();
+    method public abstract void setProxyOverride(androidx.webkit.ProxyConfig, java.util.concurrent.Executor, Runnable);
+  }
+
+  public abstract class SafeBrowsingResponseCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void backToSafety(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void proceed(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void showInterstitial(boolean);
+  }
+
+  public abstract class ServiceWorkerClientCompat {
+    ctor public ServiceWorkerClientCompat();
+    method @WorkerThread public abstract android.webkit.WebResourceResponse? shouldInterceptRequest(android.webkit.WebResourceRequest);
+  }
+
+  public abstract class ServiceWorkerControllerCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ServiceWorkerControllerCompat getInstance();
+    method public abstract androidx.webkit.ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings();
+    method public abstract void setServiceWorkerClient(androidx.webkit.ServiceWorkerClientCompat?);
+  }
+
+  public abstract class ServiceWorkerWebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowContentAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowFileAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getBlockNetworkLoads();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getCacheMode();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowContentAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowFileAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setBlockNetworkLoads(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setCacheMode(int);
+  }
+
+  public class TracingConfig {
+    method public java.util.List<java.lang.String!> getCustomIncludedCategories();
+    method public int getPredefinedCategories();
+    method public int getTracingMode();
+    field public static final int CATEGORIES_ALL = 1; // 0x1
+    field public static final int CATEGORIES_ANDROID_WEBVIEW = 2; // 0x2
+    field public static final int CATEGORIES_FRAME_VIEWER = 64; // 0x40
+    field public static final int CATEGORIES_INPUT_LATENCY = 8; // 0x8
+    field public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 32; // 0x20
+    field public static final int CATEGORIES_NONE = 0; // 0x0
+    field public static final int CATEGORIES_RENDERING = 16; // 0x10
+    field public static final int CATEGORIES_WEB_DEVELOPER = 4; // 0x4
+    field public static final int RECORD_CONTINUOUSLY = 1; // 0x1
+    field public static final int RECORD_UNTIL_FULL = 0; // 0x0
+  }
+
+  public static class TracingConfig.Builder {
+    ctor public TracingConfig.Builder();
+    method public androidx.webkit.TracingConfig.Builder addCategories(int...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.lang.String!...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.util.Collection<java.lang.String!>);
+    method public androidx.webkit.TracingConfig build();
+    method public androidx.webkit.TracingConfig.Builder setTracingMode(int);
+  }
+
+  public abstract class TracingController {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.TracingController getInstance();
+    method public abstract boolean isTracing();
+    method public abstract void start(androidx.webkit.TracingConfig);
+    method public abstract boolean stop(java.io.OutputStream?, java.util.concurrent.Executor);
+  }
+
+  public class WebMessageCompat {
+    ctor public WebMessageCompat(String?);
+    ctor public WebMessageCompat(String?, androidx.webkit.WebMessagePortCompat![]?);
+    method public String? getData();
+    method public androidx.webkit.WebMessagePortCompat![]? getPorts();
+  }
+
+  public abstract class WebMessagePortCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_CLOSE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void close();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(androidx.webkit.WebMessageCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(android.os.Handler?, androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+  }
+
+  public abstract static class WebMessagePortCompat.WebMessageCallbackCompat {
+    ctor public WebMessagePortCompat.WebMessageCallbackCompat();
+    method public void onMessage(androidx.webkit.WebMessagePortCompat, androidx.webkit.WebMessageCompat?);
+  }
+
+  public abstract class WebResourceErrorCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract CharSequence getDescription();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getErrorCode();
+  }
+
+  public class WebResourceRequestCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isRedirect(android.webkit.WebResourceRequest);
+  }
+
+  public class WebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDark(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDarkStrategy(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getSafeBrowsingEnabled(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setDisabledActionModeMenuItems(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDark(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDarkStrategy(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setOffscreenPreRaster(android.webkit.WebSettings, boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingEnabled(android.webkit.WebSettings, boolean);
+    field public static final int DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING = 2; // 0x2
+    field public static final int DARK_STRATEGY_USER_AGENT_DARKENING_ONLY = 0; // 0x0
+    field public static final int DARK_STRATEGY_WEB_THEME_DARKENING_ONLY = 1; // 0x1
+    field public static final int FORCE_DARK_AUTO = 1; // 0x1
+    field public static final int FORCE_DARK_OFF = 0; // 0x0
+    field public static final int FORCE_DARK_ON = 2; // 0x2
+  }
+
+  public final class WebViewAssetLoader {
+    method @WorkerThread public android.webkit.WebResourceResponse? shouldInterceptRequest(android.net.Uri);
+    field public static final String DEFAULT_DOMAIN = "appassets.androidplatform.net";
+  }
+
+  public static final class WebViewAssetLoader.AssetsPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.AssetsPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.Builder {
+    ctor public WebViewAssetLoader.Builder();
+    method public androidx.webkit.WebViewAssetLoader.Builder addPathHandler(String, androidx.webkit.WebViewAssetLoader.PathHandler);
+    method public androidx.webkit.WebViewAssetLoader build();
+    method public androidx.webkit.WebViewAssetLoader.Builder setDomain(String);
+    method public androidx.webkit.WebViewAssetLoader.Builder setHttpAllowed(boolean);
+  }
+
+  public static final class WebViewAssetLoader.InternalStoragePathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.InternalStoragePathHandler(android.content.Context, java.io.File);
+    method @WorkerThread public android.webkit.WebResourceResponse handle(String);
+  }
+
+  public static interface WebViewAssetLoader.PathHandler {
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.ResourcesPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.ResourcesPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public class WebViewClientCompat extends android.webkit.WebViewClient {
+    ctor public WebViewClientCompat();
+    method @RequiresApi(23) public final void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
+    method @RequiresApi(21) @UiThread public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, androidx.webkit.WebResourceErrorCompat);
+    method @RequiresApi(27) public final void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, android.webkit.SafeBrowsingResponse);
+    method @UiThread public void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, androidx.webkit.SafeBrowsingResponseCompat);
+  }
+
+  public class WebViewCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void addWebMessageListener(android.webkit.WebView, String, java.util.Set<java.lang.String!>, androidx.webkit.WebViewCompat.WebMessageListener);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebMessagePortCompat![] createWebMessageChannel(android.webkit.WebView);
+    method public static android.content.pm.PackageInfo? getCurrentWebViewPackage(android.content.Context);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_CHROME_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebChromeClient? getWebChromeClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebViewClient getWebViewClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_RENDERER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcess? getWebViewRenderProcess(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcessClient? getWebViewRenderProcessClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.MULTI_PROCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isMultiProcessEnabled();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.VISUAL_STATE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.POST_WEB_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void removeWebMessageListener(android.webkit.WebView, String);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_WHITELIST, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String!>, android.webkit.ValueCallback<java.lang.Boolean!>?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, java.util.concurrent.Executor, androidx.webkit.WebViewRenderProcessClient);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, androidx.webkit.WebViewRenderProcessClient?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.START_SAFE_BROWSING, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean!>?);
+  }
+
+  public static interface WebViewCompat.VisualStateCallback {
+    method @UiThread public void onComplete(long);
+  }
+
+  public static interface WebViewCompat.WebMessageListener {
+    method @UiThread public void onPostMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri, boolean, androidx.webkit.JavaScriptReplyProxy);
+  }
+
+  public class WebViewFeature {
+    method public static boolean isFeatureSupported(String);
+    field public static final String CREATE_WEB_MESSAGE_CHANNEL = "CREATE_WEB_MESSAGE_CHANNEL";
+    field public static final String DISABLED_ACTION_MODE_MENU_ITEMS = "DISABLED_ACTION_MODE_MENU_ITEMS";
+    field public static final String FORCE_DARK = "FORCE_DARK";
+    field public static final String FORCE_DARK_STRATEGY = "FORCE_DARK_STRATEGY";
+    field public static final String GET_WEB_CHROME_CLIENT = "GET_WEB_CHROME_CLIENT";
+    field public static final String GET_WEB_VIEW_CLIENT = "GET_WEB_VIEW_CLIENT";
+    field public static final String GET_WEB_VIEW_RENDERER = "GET_WEB_VIEW_RENDERER";
+    field public static final String MULTI_PROCESS = "MULTI_PROCESS";
+    field public static final String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
+    field public static final String POST_WEB_MESSAGE = "POST_WEB_MESSAGE";
+    field public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE";
+    field public static final String RECEIVE_HTTP_ERROR = "RECEIVE_HTTP_ERROR";
+    field public static final String RECEIVE_WEB_RESOURCE_ERROR = "RECEIVE_WEB_RESOURCE_ERROR";
+    field public static final String SAFE_BROWSING_ENABLE = "SAFE_BROWSING_ENABLE";
+    field public static final String SAFE_BROWSING_HIT = "SAFE_BROWSING_HIT";
+    field public static final String SAFE_BROWSING_PRIVACY_POLICY_URL = "SAFE_BROWSING_PRIVACY_POLICY_URL";
+    field public static final String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY = "SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY";
+    field public static final String SAFE_BROWSING_RESPONSE_PROCEED = "SAFE_BROWSING_RESPONSE_PROCEED";
+    field public static final String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL = "SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL";
+    field public static final String SAFE_BROWSING_WHITELIST = "SAFE_BROWSING_WHITELIST";
+    field public static final String SERVICE_WORKER_BASIC_USAGE = "SERVICE_WORKER_BASIC_USAGE";
+    field public static final String SERVICE_WORKER_BLOCK_NETWORK_LOADS = "SERVICE_WORKER_BLOCK_NETWORK_LOADS";
+    field public static final String SERVICE_WORKER_CACHE_MODE = "SERVICE_WORKER_CACHE_MODE";
+    field public static final String SERVICE_WORKER_CONTENT_ACCESS = "SERVICE_WORKER_CONTENT_ACCESS";
+    field public static final String SERVICE_WORKER_FILE_ACCESS = "SERVICE_WORKER_FILE_ACCESS";
+    field public static final String SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST = "SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST";
+    field public static final String SHOULD_OVERRIDE_WITH_REDIRECTS = "SHOULD_OVERRIDE_WITH_REDIRECTS";
+    field public static final String START_SAFE_BROWSING = "START_SAFE_BROWSING";
+    field public static final String TRACING_CONTROLLER_BASIC_USAGE = "TRACING_CONTROLLER_BASIC_USAGE";
+    field public static final String VISUAL_STATE_CALLBACK = "VISUAL_STATE_CALLBACK";
+    field public static final String WEB_MESSAGE_CALLBACK_ON_MESSAGE = "WEB_MESSAGE_CALLBACK_ON_MESSAGE";
+    field public static final String WEB_MESSAGE_LISTENER = "WEB_MESSAGE_LISTENER";
+    field public static final String WEB_MESSAGE_PORT_CLOSE = "WEB_MESSAGE_PORT_CLOSE";
+    field public static final String WEB_MESSAGE_PORT_POST_MESSAGE = "WEB_MESSAGE_PORT_POST_MESSAGE";
+    field public static final String WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK = "WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK";
+    field public static final String WEB_RESOURCE_ERROR_GET_CODE = "WEB_RESOURCE_ERROR_GET_CODE";
+    field public static final String WEB_RESOURCE_ERROR_GET_DESCRIPTION = "WEB_RESOURCE_ERROR_GET_DESCRIPTION";
+    field public static final String WEB_RESOURCE_REQUEST_IS_REDIRECT = "WEB_RESOURCE_REQUEST_IS_REDIRECT";
+    field public static final String WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE = "WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE";
+    field public static final String WEB_VIEW_RENDERER_TERMINATE = "WEB_VIEW_RENDERER_TERMINATE";
+  }
+
+  public abstract class WebViewRenderProcess {
+    ctor public WebViewRenderProcess();
+    method public abstract boolean terminate();
+  }
+
+  public abstract class WebViewRenderProcessClient {
+    ctor public WebViewRenderProcessClient();
+    method public abstract void onRenderProcessResponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+    method public abstract void onRenderProcessUnresponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+  }
+
+}
+
diff --git a/webkit/webkit/api/res-1.3.0-rc01.txt b/webkit/webkit/api/res-1.3.0-rc01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/webkit/webkit/api/res-1.3.0-rc01.txt
diff --git a/webkit/webkit/api/restricted_1.3.0-rc01.txt b/webkit/webkit/api/restricted_1.3.0-rc01.txt
new file mode 100644
index 0000000..57f9939
--- /dev/null
+++ b/webkit/webkit/api/restricted_1.3.0-rc01.txt
@@ -0,0 +1,270 @@
+// Signature format: 3.0
+package androidx.webkit {
+
+  public abstract class JavaScriptReplyProxy {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(String);
+  }
+
+  public final class ProxyConfig {
+    method public java.util.List<java.lang.String!> getBypassRules();
+    method public java.util.List<androidx.webkit.ProxyConfig.ProxyRule!> getProxyRules();
+    field public static final String MATCH_ALL_SCHEMES = "*";
+    field public static final String MATCH_HTTP = "http";
+    field public static final String MATCH_HTTPS = "https";
+  }
+
+  public static final class ProxyConfig.Builder {
+    ctor public ProxyConfig.Builder();
+    ctor public ProxyConfig.Builder(androidx.webkit.ProxyConfig);
+    method public androidx.webkit.ProxyConfig.Builder addBypassRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect(String);
+    method public androidx.webkit.ProxyConfig.Builder addDirect();
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String);
+    method public androidx.webkit.ProxyConfig.Builder addProxyRule(String, String);
+    method public androidx.webkit.ProxyConfig build();
+    method public androidx.webkit.ProxyConfig.Builder bypassSimpleHostnames();
+    method public androidx.webkit.ProxyConfig.Builder removeImplicitRules();
+  }
+
+  public static final class ProxyConfig.ProxyRule {
+    method public String getSchemeFilter();
+    method public String getUrl();
+  }
+
+  public abstract class ProxyController {
+    method public abstract void clearProxyOverride(java.util.concurrent.Executor, Runnable);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.PROXY_OVERRIDE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ProxyController getInstance();
+    method public abstract void setProxyOverride(androidx.webkit.ProxyConfig, java.util.concurrent.Executor, Runnable);
+  }
+
+  public abstract class SafeBrowsingResponseCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void backToSafety(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void proceed(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void showInterstitial(boolean);
+  }
+
+  public abstract class ServiceWorkerClientCompat {
+    ctor public ServiceWorkerClientCompat();
+    method @WorkerThread public abstract android.webkit.WebResourceResponse? shouldInterceptRequest(android.webkit.WebResourceRequest);
+  }
+
+  public abstract class ServiceWorkerControllerCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.ServiceWorkerControllerCompat getInstance();
+    method public abstract androidx.webkit.ServiceWorkerWebSettingsCompat getServiceWorkerWebSettings();
+    method public abstract void setServiceWorkerClient(androidx.webkit.ServiceWorkerClientCompat?);
+  }
+
+  public abstract class ServiceWorkerWebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowContentAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getAllowFileAccess();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract boolean getBlockNetworkLoads();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getCacheMode();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowContentAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_FILE_ACCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setAllowFileAccess(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setBlockNetworkLoads(boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SERVICE_WORKER_CACHE_MODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setCacheMode(int);
+  }
+
+  public class TracingConfig {
+    method public java.util.List<java.lang.String!> getCustomIncludedCategories();
+    method public int getPredefinedCategories();
+    method public int getTracingMode();
+    field public static final int CATEGORIES_ALL = 1; // 0x1
+    field public static final int CATEGORIES_ANDROID_WEBVIEW = 2; // 0x2
+    field public static final int CATEGORIES_FRAME_VIEWER = 64; // 0x40
+    field public static final int CATEGORIES_INPUT_LATENCY = 8; // 0x8
+    field public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING = 32; // 0x20
+    field public static final int CATEGORIES_NONE = 0; // 0x0
+    field public static final int CATEGORIES_RENDERING = 16; // 0x10
+    field public static final int CATEGORIES_WEB_DEVELOPER = 4; // 0x4
+    field public static final int RECORD_CONTINUOUSLY = 1; // 0x1
+    field public static final int RECORD_UNTIL_FULL = 0; // 0x0
+  }
+
+  public static class TracingConfig.Builder {
+    ctor public TracingConfig.Builder();
+    method public androidx.webkit.TracingConfig.Builder addCategories(int...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.lang.String!...);
+    method public androidx.webkit.TracingConfig.Builder addCategories(java.util.Collection<java.lang.String!>);
+    method public androidx.webkit.TracingConfig build();
+    method public androidx.webkit.TracingConfig.Builder setTracingMode(int);
+  }
+
+  public abstract class TracingController {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.TracingController getInstance();
+    method public abstract boolean isTracing();
+    method public abstract void start(androidx.webkit.TracingConfig);
+    method public abstract boolean stop(java.io.OutputStream?, java.util.concurrent.Executor);
+  }
+
+  public class WebMessageCompat {
+    ctor public WebMessageCompat(String?);
+    ctor public WebMessageCompat(String?, androidx.webkit.WebMessagePortCompat![]?);
+    method public String? getData();
+    method public androidx.webkit.WebMessagePortCompat![]? getPorts();
+  }
+
+  public abstract class WebMessagePortCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_CLOSE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void close();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void postMessage(androidx.webkit.WebMessageCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract void setWebMessageCallback(android.os.Handler?, androidx.webkit.WebMessagePortCompat.WebMessageCallbackCompat);
+  }
+
+  public abstract static class WebMessagePortCompat.WebMessageCallbackCompat {
+    ctor public WebMessagePortCompat.WebMessageCallbackCompat();
+    method public void onMessage(androidx.webkit.WebMessagePortCompat, androidx.webkit.WebMessageCompat?);
+  }
+
+  public abstract class WebResourceErrorCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract CharSequence getDescription();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public abstract int getErrorCode();
+  }
+
+  public class WebResourceRequestCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isRedirect(android.webkit.WebResourceRequest);
+  }
+
+  public class WebSettingsCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDark(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static int getForceDarkStrategy(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean getSafeBrowsingEnabled(android.webkit.WebSettings);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setDisabledActionModeMenuItems(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDark(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.FORCE_DARK_STRATEGY, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setForceDarkStrategy(android.webkit.WebSettings, int);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.OFF_SCREEN_PRERASTER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setOffscreenPreRaster(android.webkit.WebSettings, boolean);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_ENABLE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingEnabled(android.webkit.WebSettings, boolean);
+    field public static final int DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING = 2; // 0x2
+    field public static final int DARK_STRATEGY_USER_AGENT_DARKENING_ONLY = 0; // 0x0
+    field public static final int DARK_STRATEGY_WEB_THEME_DARKENING_ONLY = 1; // 0x1
+    field public static final int FORCE_DARK_AUTO = 1; // 0x1
+    field public static final int FORCE_DARK_OFF = 0; // 0x0
+    field public static final int FORCE_DARK_ON = 2; // 0x2
+  }
+
+  public final class WebViewAssetLoader {
+    method @WorkerThread public android.webkit.WebResourceResponse? shouldInterceptRequest(android.net.Uri);
+    field public static final String DEFAULT_DOMAIN = "appassets.androidplatform.net";
+  }
+
+  public static final class WebViewAssetLoader.AssetsPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.AssetsPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.Builder {
+    ctor public WebViewAssetLoader.Builder();
+    method public androidx.webkit.WebViewAssetLoader.Builder addPathHandler(String, androidx.webkit.WebViewAssetLoader.PathHandler);
+    method public androidx.webkit.WebViewAssetLoader build();
+    method public androidx.webkit.WebViewAssetLoader.Builder setDomain(String);
+    method public androidx.webkit.WebViewAssetLoader.Builder setHttpAllowed(boolean);
+  }
+
+  public static final class WebViewAssetLoader.InternalStoragePathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.InternalStoragePathHandler(android.content.Context, java.io.File);
+    method @WorkerThread public android.webkit.WebResourceResponse handle(String);
+  }
+
+  public static interface WebViewAssetLoader.PathHandler {
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public static final class WebViewAssetLoader.ResourcesPathHandler implements androidx.webkit.WebViewAssetLoader.PathHandler {
+    ctor public WebViewAssetLoader.ResourcesPathHandler(android.content.Context);
+    method @WorkerThread public android.webkit.WebResourceResponse? handle(String);
+  }
+
+  public class WebViewClientCompat extends android.webkit.WebViewClient {
+    ctor public WebViewClientCompat();
+    method @RequiresApi(23) public final void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
+    method @RequiresApi(21) @UiThread public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, androidx.webkit.WebResourceErrorCompat);
+    method @RequiresApi(27) public final void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, android.webkit.SafeBrowsingResponse);
+    method @UiThread public void onSafeBrowsingHit(android.webkit.WebView, android.webkit.WebResourceRequest, int, androidx.webkit.SafeBrowsingResponseCompat);
+  }
+
+  public class WebViewCompat {
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void addWebMessageListener(android.webkit.WebView, String, java.util.Set<java.lang.String!>, androidx.webkit.WebViewCompat.WebMessageListener);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebMessagePortCompat![] createWebMessageChannel(android.webkit.WebView);
+    method public static android.content.pm.PackageInfo? getCurrentWebViewPackage(android.content.Context);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_CHROME_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebChromeClient? getWebChromeClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_CLIENT, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static android.webkit.WebViewClient getWebViewClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.GET_WEB_VIEW_RENDERER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcess? getWebViewRenderProcess(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static androidx.webkit.WebViewRenderProcessClient? getWebViewRenderProcessClient(android.webkit.WebView);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.MULTI_PROCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isMultiProcessEnabled();
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.VISUAL_STATE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.POST_WEB_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void removeWebMessageListener(android.webkit.WebView, String);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.SAFE_BROWSING_WHITELIST, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String!>, android.webkit.ValueCallback<java.lang.Boolean!>?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, java.util.concurrent.Executor, androidx.webkit.WebViewRenderProcessClient);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setWebViewRenderProcessClient(android.webkit.WebView, androidx.webkit.WebViewRenderProcessClient?);
+    method @RequiresFeature(name=androidx.webkit.WebViewFeature.START_SAFE_BROWSING, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean!>?);
+  }
+
+  public static interface WebViewCompat.VisualStateCallback {
+    method @UiThread public void onComplete(long);
+  }
+
+  public static interface WebViewCompat.WebMessageListener {
+    method @UiThread public void onPostMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri, boolean, androidx.webkit.JavaScriptReplyProxy);
+  }
+
+  public class WebViewFeature {
+    method public static boolean isFeatureSupported(String);
+    field public static final String CREATE_WEB_MESSAGE_CHANNEL = "CREATE_WEB_MESSAGE_CHANNEL";
+    field public static final String DISABLED_ACTION_MODE_MENU_ITEMS = "DISABLED_ACTION_MODE_MENU_ITEMS";
+    field public static final String FORCE_DARK = "FORCE_DARK";
+    field public static final String FORCE_DARK_STRATEGY = "FORCE_DARK_STRATEGY";
+    field public static final String GET_WEB_CHROME_CLIENT = "GET_WEB_CHROME_CLIENT";
+    field public static final String GET_WEB_VIEW_CLIENT = "GET_WEB_VIEW_CLIENT";
+    field public static final String GET_WEB_VIEW_RENDERER = "GET_WEB_VIEW_RENDERER";
+    field public static final String MULTI_PROCESS = "MULTI_PROCESS";
+    field public static final String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
+    field public static final String POST_WEB_MESSAGE = "POST_WEB_MESSAGE";
+    field public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE";
+    field public static final String RECEIVE_HTTP_ERROR = "RECEIVE_HTTP_ERROR";
+    field public static final String RECEIVE_WEB_RESOURCE_ERROR = "RECEIVE_WEB_RESOURCE_ERROR";
+    field public static final String SAFE_BROWSING_ENABLE = "SAFE_BROWSING_ENABLE";
+    field public static final String SAFE_BROWSING_HIT = "SAFE_BROWSING_HIT";
+    field public static final String SAFE_BROWSING_PRIVACY_POLICY_URL = "SAFE_BROWSING_PRIVACY_POLICY_URL";
+    field public static final String SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY = "SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY";
+    field public static final String SAFE_BROWSING_RESPONSE_PROCEED = "SAFE_BROWSING_RESPONSE_PROCEED";
+    field public static final String SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL = "SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL";
+    field public static final String SAFE_BROWSING_WHITELIST = "SAFE_BROWSING_WHITELIST";
+    field public static final String SERVICE_WORKER_BASIC_USAGE = "SERVICE_WORKER_BASIC_USAGE";
+    field public static final String SERVICE_WORKER_BLOCK_NETWORK_LOADS = "SERVICE_WORKER_BLOCK_NETWORK_LOADS";
+    field public static final String SERVICE_WORKER_CACHE_MODE = "SERVICE_WORKER_CACHE_MODE";
+    field public static final String SERVICE_WORKER_CONTENT_ACCESS = "SERVICE_WORKER_CONTENT_ACCESS";
+    field public static final String SERVICE_WORKER_FILE_ACCESS = "SERVICE_WORKER_FILE_ACCESS";
+    field public static final String SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST = "SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST";
+    field public static final String SHOULD_OVERRIDE_WITH_REDIRECTS = "SHOULD_OVERRIDE_WITH_REDIRECTS";
+    field public static final String START_SAFE_BROWSING = "START_SAFE_BROWSING";
+    field public static final String TRACING_CONTROLLER_BASIC_USAGE = "TRACING_CONTROLLER_BASIC_USAGE";
+    field public static final String VISUAL_STATE_CALLBACK = "VISUAL_STATE_CALLBACK";
+    field public static final String WEB_MESSAGE_CALLBACK_ON_MESSAGE = "WEB_MESSAGE_CALLBACK_ON_MESSAGE";
+    field public static final String WEB_MESSAGE_LISTENER = "WEB_MESSAGE_LISTENER";
+    field public static final String WEB_MESSAGE_PORT_CLOSE = "WEB_MESSAGE_PORT_CLOSE";
+    field public static final String WEB_MESSAGE_PORT_POST_MESSAGE = "WEB_MESSAGE_PORT_POST_MESSAGE";
+    field public static final String WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK = "WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK";
+    field public static final String WEB_RESOURCE_ERROR_GET_CODE = "WEB_RESOURCE_ERROR_GET_CODE";
+    field public static final String WEB_RESOURCE_ERROR_GET_DESCRIPTION = "WEB_RESOURCE_ERROR_GET_DESCRIPTION";
+    field public static final String WEB_RESOURCE_REQUEST_IS_REDIRECT = "WEB_RESOURCE_REQUEST_IS_REDIRECT";
+    field public static final String WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE = "WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE";
+    field public static final String WEB_VIEW_RENDERER_TERMINATE = "WEB_VIEW_RENDERER_TERMINATE";
+  }
+
+  public abstract class WebViewRenderProcess {
+    ctor public WebViewRenderProcess();
+    method public abstract boolean terminate();
+  }
+
+  public abstract class WebViewRenderProcessClient {
+    ctor public WebViewRenderProcessClient();
+    method public abstract void onRenderProcessResponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+    method public abstract void onRenderProcessUnresponsive(android.webkit.WebView, androidx.webkit.WebViewRenderProcess?);
+  }
+
+}
+
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/background/greedy/GreedySchedulerTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/background/greedy/GreedySchedulerTest.java
index 7ab17a0..f6b15d3 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/background/greedy/GreedySchedulerTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/background/greedy/GreedySchedulerTest.java
@@ -75,6 +75,7 @@
                 mContext,
                 mWorkManagerImpl,
                 mMockWorkConstraintsTracker);
+        mGreedyScheduler.mIsMainProcess = true;
         mDelayedWorkTracker = mock(DelayedWorkTracker.class);
         mGreedyScheduler.setDelayedWorkTracker(mDelayedWorkTracker);
     }
@@ -192,7 +193,7 @@
     @SmallTest
     public void testGreedyScheduler_ignoresRequestsInADifferentProcess() {
         // Context.getSystemService() returns null so no work should be executed.
-        when(mContext.getPackageName()).thenReturn("packageName");
+        mGreedyScheduler.mIsMainProcess = false;
         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
         WorkSpec workSpec = getWorkSpec(work);
         mGreedyScheduler.schedule(workSpec);
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java b/work/workmanager/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
index 3c9feb12..a0f0d47 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
@@ -20,6 +20,7 @@
 import static android.os.Build.VERSION.SDK_INT;
 
 import android.app.ActivityManager;
+import android.app.Application;
 import android.content.Context;
 import android.os.Process;
 import android.text.TextUtils;
@@ -39,6 +40,7 @@
 import androidx.work.impl.model.WorkSpec;
 import androidx.work.impl.utils.taskexecutor.TaskExecutor;
 
+import java.lang.reflect.Method;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -64,7 +66,7 @@
     private final Object mLock;
 
     // Internal State
-    private Boolean mIsMainProcess;
+    Boolean mIsMainProcess;
 
     public GreedyScheduler(
             @NonNull Context context,
@@ -237,6 +239,37 @@
 
     @Nullable
     private String getProcessName() {
+        if (SDK_INT >= 28) {
+            return Application.getProcessName();
+        }
+
+        // Try using ActivityThread to determine the current process name.
+        try {
+            Class<?> activityThread = Class.forName(
+                    "android.app.ActivityThread",
+                    false,
+                    GreedyScheduler.class.getClassLoader());
+            final Object packageName;
+            if (SDK_INT >= 18) {
+                Method currentProcessName = activityThread.getDeclaredMethod("currentProcessName");
+                currentProcessName.setAccessible(true);
+                packageName = currentProcessName.invoke(null);
+            } else {
+                Method getActivityThread = activityThread.getDeclaredMethod(
+                        "currentActivityThread");
+                getActivityThread.setAccessible(true);
+                Method getProcessName = activityThread.getDeclaredMethod("getProcessName");
+                getProcessName.setAccessible(true);
+                packageName = getProcessName.invoke(getActivityThread.invoke(null));
+            }
+            if (packageName instanceof String) {
+                return (String) packageName;
+            }
+        } catch (Throwable exception) {
+            Logger.get().debug(TAG, "Unable to check ActivityThread for processName", exception);
+        }
+
+        // Fallback to the most expensive way
         int pid = Process.myPid();
         ActivityManager am =
                 (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);